16.4 auto_ptr类
auto_ptr类是个模板类,auto_ptr又常常被称为智能指针,它巧妙地利用C++退出作用域时会自动释放变量的机制,来清理其维护的对象。根据前面的内容可知,用指针申请动态内存时,如果不先对动态内存进行释放就销毁指针,会造成内存泄露。那有没有可能引入一种机制,当指针被撤销时,其指向的动态内存会被自动释放,这样不仅可以避免程序员遗忘带来的内存泄露,也使得程序的结构更为优雅,而且在某些场合下,程序员很难判断到底在什么位置对内存进行释放较为合适,如下所示。
char*GetMem(int n) { char*p=new char[100]; return p; }
上述函数用于申请一块动态内存,并返回指向该块内存的指针,当申请不成功时,返回null,申请到的内存块是供外部使用的,何时释放也取决于具体的需要,有时候很难判断,这很容易造成内存泄露,给程序带来安全隐患。
如何做到这一点呢?使用普通的指针显然是不行的,那能否对其进行封装,这样在对象过期时,析构函数被调用,释放其指向的内存呢?这也是auto_ptr类模板的由来。
16.4.1 使用auto_ptr类模板
使用auto_ptr时,需要使用头文件memory,该文件中定义了auto_ptr类模板,在程序中只要对其实例化即可使用,其定义如下所示。
template<class T> class auto_ptr { public: explicit auto_ptr(X*p=0)throw(); …… }举例如下所示。 auto_ptr<int>pi(new int); auto_ptr<string>ps(new string);
这样,可将auto_ptr实例化后创建的类对象pi和ps当成一种“高级指针”或“智能指针”来看,不用再对动态内存进行delete释放,对应内存的清理工作在pi和ps被撤销时自动执行。
auto_ptr中的构造函数是显式(Explicit)的,因此,下列隐式转换都是非法的。
int*p=new int; auto_ptr<int>pi;//pi用空指针初始化 pi=p;//错误,隐式转换 及 auto_ptr<int>pi=p;//错误,隐式转换除此之外,完全可以把auto_ptr实例化后的对象当成指针来用,可以对其间接引用(dereference,如*pi),如果类型T是某个类,还可以使用auto_ptr访问其成员(->),可将其赋给常规类型的指针,如下所示。 auto_ptr<int>pi(new int); int*p=pi;
此外,auto_ptr还支持同类型间的赋值,但和普通的赋值有所不同,把一个auto_ptr赋值给另一个auto_ptr,前一个auto_ptr就会变成null值,这在稍后会进行讲解。