动态内存使用最多的是在C++应用程序的代码中。有过编程经验的程序员虽然都知道new操作符的使用一定要与delete匹配,在某些场合仍然可能有内存溢出。当异常被掷出时,程序的正常控制流程被改变,因此导致潜在的内存溢出。例如, |
|
当 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对象的例子: |
|
auto_ptr后面的尖括弧里指定auto_ptr指针的类型,在这个例子中是string。然后auto_ptr句柄的名字,在这个例子中是pstr。最后是用动态分配的对象指针初始化这个实例。注意你只能使用auto_ptr构造器的拷贝,也就是说,下面的代码是非法的: |
|
Auto_ptr是一个模板,因此它是完全通用的。它可以指向任何类型的对象,包括基本的数据类型: |
|
一旦你实例化一个auto_ptr,并用动态分配的对象地址对它进行了初始化,就可以将它当作普通的对象指针使用,例如: |
|
之所以能这样做是因为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就实现了自动和安全的本地对象。
如何避免使用auto_ptr的缺陷
auto_ptr并不是完美无缺的,它的确很方便,但也有缺陷,在使用时要注意避免。首先,不要将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做,否则可能会碰到不可预见的结果(在另文中讨论)。
auto_ptr的另一个缺陷是将数组作为auto_ptr的参数: |
|
记住不管什么时候使用数组的new操作时,必须要用delete[]来摧毁数组。因为auto_ptr的析构函数只对非数组类型起作用。所以数组是不能被正确摧毁的话,程序的行为是不明确的。总之,auto_ptr控制一个由new分配的单对象指针,仅此而已。 |
相关推荐
auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者。当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的...
auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同一时候被分给两个这样拥有者(auto_ptr)。 当auto_ptr对象生命周期结束时。其析构...
auto_ptr 是C++标准库提供的类模板,auto_ptr对象通过初始化指向由new创建的动态内存,它是这块内存的拥有者,一块内存不能同时被分给两个拥有者。当auto_ptr对象生命周期结束时,其析构函数会将auto_ptr对象拥有的...
shared_ptr(智能指针)举例 程序使⽤动态内存出于以下三种原因之⼀ : 1、程序不知道⾃⼰需要多少对象; 2、程序不知道所需对象的准确类型; 3、程序需要在多个对象间共享数据 ⼀. 要确保⽤ new 动态分配的内存空间...
share_ptr 智能指针是(⼏乎总是)模板类,shared_ptr 同样是模板类,所以在创建 shared_ptr 时需要指定其指向的类型。shared_ptr 负责在不使 ⽤实例时释放由它管理的对象,同时它可以⾃由的共享它指向的对象。 ...
智能指针 智能指针shared_ptr的初始化 的初始化 shared_ptr是智能指针,是模板,头⽂件是memory: shared_ptr<string> p1 最安全的使⽤⽅法是调⽤make_shared标准库函数,此函数在动态内存中分配⼀个对象并初始化它...
C++ 标准库有四种智能指针:auto_ptr,unique_ptr,shared_ptr,weak_ptr(auto_ptr 是 C++98 标准的,其余都是 C++11 标准推出的,auto_ptr 现在已经不再使⽤了),C++11 这三种智能指针都是类模板。 ⼆ ⼆. ...
//先写⼀个测试类 main函数如下: int _tmain(int argc, _TCHAR* argv[]) { auto_ptr <Base1> base1(new Base1);//可理解为先声明⼀个名为base1的Base1类型智能指针,然后再base1⾥⾯管理new Base1 if (base1.get())...
13.5 动态内存管理类 464 13.6 对象移动 470 13.6.1 右值引用 471 13.6.2 移动构造函数和移动赋值运算符 473 13.6.3 右值引用和成员函数 481 小结 486 术语表 486 第14章 操作重载与类型转换 489 ...
13.5 动态内存管理类 464 13.6 对象移动 470 13.6.1 右值引用 471 13.6.2 移动构造函数和移动赋值运算符 473 13.6.3 右值引用和成员函数 481 小结 486 术语表 486 第14章 操作重载与类型转换 489 ...
17.1.9 auto_ptr类 591 17.1.10 异常说明 595 17.1.11 函数指针的异常说明 598 17.2 命名空间 599 17.2.1 命名空间的定义 599 17.2.2 嵌套命名空间 603 17.2.3 未命名的命名空间 604 17.2.4 命名空间成员的使用 606 ...
13.15 auto_ptr类与动态内存分配 13.16 标准库异常层次 小结 术语 自测练习 自测练习答案 练习 第14章 文件处理 14.1 简介 14.2 数据的层次 14.3 文件和流 14.4 建立顺序访问文件 14.5 读取顺序访问文件中的...
13.15 auto_ptr类与动态内存分配 13.16 标准库异常层次 小结 术语 自测练习 自测练习答案 练习 第14章 文件处理 14.1 简介 14.2 数据的层次 14.3 文件和流 14.4 建立顺序访问文件 14.5 读取顺序访问文件中的...
1.5.3 auto_ptr 1.5.4 函数级的try块 1.6 标准异常 1.7 异常规格说明 1.7.1 更好的异常规格说明 1.7.2 异常规格说明和继承 1.7.3 什么时候不使用异常规格说明 1.8 异常安全 ...
1.17 内存的概念-------------------------------------------------------18 1.18 算术运算---------------------------------------------------------19 1.19 判断:相等与关系运算------------------------...