用auto_ptr类模板帮助动态内存管理

动态内存使用最多的是在C++应用程序的代码中。有过编程经验的程序员虽然都知道new操作符的使用一定要与delete匹配,在某些场合仍然可能有内存溢出。当异常被掷出时,程序的正常控制流程被改变,因此导致潜在的内存溢出。例如,

void g() //可能掷出
{
  if (some_condition == false)
   throw X();
}
void func()
{
  string * pstr = new string;
  g(); //如果 g 掷出一个异常,内存溢出
  delete pstr; //如果 g 掷出一个异常,则此行为不能达到的代码行。
}
int main()
{
  try
  {
   func();
  }
  catch(...)
  {}
}

当 g 掷出一个异常,异常处理机制展开堆栈:g()退出,同时控制被转移到 main() 的 catch(...)代码块。这时,无论怎样,func()中的delete语句都不会被执行,由此导致pstr的内存溢出。要是使用局部自动串变量,而不是使用动态分配-内存溢出就不会出现了:string str; //局部自动对象
g(); //没有内存溢出

许多数据重要的结构以及应用,象链表,STL容器,串,数据库系统以及交互式应用必须使用动态内存分配,因此仍然冒着万一发生异常导致内存溢出的风险。C++标准化委员会意识到了这个漏洞并在标准库中添加了一个特殊的类模板,它就是std::auto_ptr,其目的是促使动态内存和异常之前进行平滑的交互。Auto_ptr保证当异常掷出时分配的对象(即:new操作符分配的对象)能被自动销毁,内存能被自动释放。下面我们就来讨论使用动态内存时,如何正确和有效地使用auto_ptr来避免资源溢出。这个技术适用于文件,线程,锁定以及与此类似的资源。

Auto_ptr的定义可以在<memory.h>中找到。与标准库中其它的成员一样,它被声明在命名空间std::中。当你实例化auto_ptr对象时,对它进行初始化的方法是用一个指针指向动态分配的对象,下面是实例化和初始化auto_ptr对象的例子:

#include <memory>
#include <string>
using namespace std;
void func()
{
  auto_ptr<string> pstr (new string); /* 创建并初始化auto_ptr */
}

auto_ptr后面的尖括弧里指定auto_ptr指针的类型,在这个例子中是string。然后auto_ptr句柄的名字,在这个例子中是pstr。最后是用动态分配的对象指针初始化这个实例。注意你只能使用auto_ptr构造器的拷贝,也就是说,下面的代码是非法的:

auto_ptr<string> pstr = new string; //编译出错

Auto_ptr是一个模板,因此它是完全通用的。它可以指向任何类型的对象,包括基本的数据类型:

auto_ptr<int> pi (new int);

一旦你实例化一个auto_ptr,并用动态分配的对象地址对它进行了初始化,就可以将它当作普通的对象指针使用,例如:

*pstr = "hello world"; //赋值
 pstr->size(); //调用成员函数

之所以能这样做是因为auto_ptr重载了操作符&,*和->。不要被语法误导,记住pstr是一个对象,不是一个指针。

auto_ptr是如何解决前面提到的内存溢出问题呢?auto_ptr的析构函数自动摧毁它绑定的动态分配对象。换句话说,当pstr的析构函数执行时,它删除构造pstr期间创建的串指针。你绝不能删除auto_ptr,因为它是一个本地对象,它的析构函数是被自动调用的。让我们看一下函数func()的修订版本,这次使用了auto_ptr:

void func()
 {
  auto_ptr<string> pstr (new string);
  g(); //如果g()掷出异常,pstr 被自动摧毁
 }

C++保证在堆栈展开过程中,自动存储类型的对象被自动摧毁。因此,如果g()掷出异常,pstr的析构函数将会在控制被转移到catch(...)块之前执行。因为pstr的析构函数删除其绑定的串指针,所以不会有内存溢出发生。这样我们在使用动态分配对象时,利用auto_ptr就实现了自动和安全的本地对象。

时间: 2024-11-02 16:20:52

用auto_ptr类模板帮助动态内存管理的相关文章

c++ 动态内存管理类 静态成员

问题描述 c++ 动态内存管理类 静态成员 C++primer 5th private 中 alloc 是static吗?是的话默认构造函数应该初始化没了,应该还要定义. 解决方案 动态内存管理类 解决方案二: 有static才是静态的.但它allocator的实现可能达到了静态的效果.

c++中 类 指针数组 动态内存

问题描述 c++中 类 指针数组 动态内存 小白问题 关于类的指针数组中 动态内存分配问题 如何来运用 求讲解 解决方案 看看这文章http://blog.csdn.net/lanbing510/article/details/8112786 解决方案二: 你应该属于初学者,应该多看书,多编写程序,验证自己的思想,这才会进步的快,对于参考书,你可以参考这里让你走上牛人的C++学习书籍推荐,半年后你就会觉得你问的问题根本不叫问题,对于动态内存,你可以参考指针参数是如何传递内存的?和既然有了mall

理解C语言——从小菜到大神的晋级之路(12)——动态内存管理

      本节视频链接:点击这里         在前面的内容中,我们通常使用数组来利用一段连续的内存空间来保存数据.我们前面用到的数组基本保存在栈内存中,其内存空间由系统自动分配和释放,使用非常方便,也不用担心内存管理的问题.但是在栈中分配的数组存在一个严重的问题,就是它的长度必须在建立时明确指定,且无法再运行时修改.为了防止运行时出现内存空间不够的问题,在编程时就必须定义一个非常大的数组来容纳理论上可能的最多个的元素,这样就会导致内存利用率底下,因为如果元素个数较少时大部分的内存空间都被浪

清明节期间学习记录,无愧对先人啊~~~LINUX ANSI C动态内存管理示范代码

我们重庆万州家人习俗是春节时为祖先上坟的. 今年回家时,我和小孩,老婆,爸妈去祖上除过草,挂过纸,放过鞭炮了. 希望祖上在另一个世界,一切安好. 清明节期间,努力学习,无愧对先人吧... 1 [root@localhost ccode]# cat realloc_example.c 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 int main(int argc, char* argv[], char* envp[]) 6 { 7 i

C++内存管理学习笔记(6)

/****************************************************************/ /*            学习是合作和分享式的! /* Author:Atlas                    Email:wdzxl198@163.com    /*  转载请注明本文出处: *   http://blog.csdn.net/wdzxl198/article/details/9120635 /**********************

动态内存和智能指针

由编译器自动分配的内存都有着严格的生存期.全局对象在程序启动时分配,在程序结束时销毁.对于局部自动对象,当我们进入其定义所在的程序块时被创建,在离开块时销毁.局部static对象在第一次使用前分配,在程序结束时销毁. 除了自动和static对象外,C++还支持动态分配对象.动态分配的对象的生存期与它们在哪里创建是无关的,只有当显式地被释放时,这些对象才会销毁.   静态内存用来保存局部static对象,类static数据成员以及定义在任何函数之外的变量.栈内存用来保存定义在函数内的非static

高质量C++/C编程指南-第7章-内存管理(4)

7.5 free和delete把指针怎么啦?7.7 杜绝"野指针""野指针"不是NULL指针,是指向"垃圾"内存的指针.人们一般不会错用NULL指针,因为用if语句很容易判断.但是"野指针"是很危险的,if语句对它不起作用. "野指针"的成因主要有两种: (1)指针变量没有被初始化.任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气.所以,指针变量在创建的同时应当被初始化,要么

Linux编程C++内存管理的指针传递详解

指针参数是如何传递内存的? 如果函数的参数是一个指针,不要指望用该指针去申请动态内存.示例7-4-1中,Test函数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么? 1 2 3 4 5 6 7 8 9 10 void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(char) * num); } void Test(void) { char *str = NULL; GetMe

cocos2dx 内存管理

cocos2dx的内存管理移植自Objective-C, 对于没有接触过OC的C++开发人员来说是挺迷惑的.不深入理解内存管理是无法写出好的C++程序的,我用OC和cocos2dx也有一段时间了,在此总结一下,希望对想用cocos2dx开发游戏的朋友有所帮助. C++的动态内存管理一般建议遵循谁申请谁释放的原则,即谁通过new操作符创建了对象,谁就负责通过delete来释放对象.如果对象的生命周期在一个函数内,这很容易做到,在函数返回前delete就行了.但一般我们在函数中new出来的对象的生命