代码改变世界

智能指针之auto_ptr

2014-04-23 13:25  放作夥  阅读(255)  评论(0编辑  收藏  举报
auto_ptr是C++标准库里的所谓智能指针之一。是用来防止内存泄漏的一种方式。
它不允许多个指针指向同一块内存,而且能在方法返回时自动释放所指的内存。这样即使在程序因为异常退出时也能释放掉所占用的资源,不用造成内存泄漏。
void f()
{
    classA* ptr = new classA;
    try{
    ...
    }
    catch(...){
   delete ptr;
   throw;
    }
delete ptr;
}
这样也可以达到没有内存泄漏的目的,但是代码量比较大,很麻烦。
#include <memory>
void f()
{
   std::auto_ptr<classA> ptr(new classA);
   ...
}
这样比较方便,不需要再delete,甚至不用catch,内存也不会泄漏。
 
auto_ptr和普通的指针的用法一样,*是取值,->用来访问成员,但是它没有提供指针的数值运算,比如++。而且也不允许通过将普通对象的指针赋值给它来初始化。如:
std::auto_ptr<classA> ptr1<new classA>;  //OK
std::auto_ptr<classA> ptr2= new calssA;  //ERROR
第二个就是非法的,因为auto_ptr不能指向普通指针,只能指向auto_ptr类型。
 
auto_ptr指针所指的数据,只能有一个指针指向,当指针发生赋值时,其实原指针就为NULL,即它不指向任何对象了。
std::auto_ptr<classA> ptr1<new classA>; 
std::auto_ptr<classA> ptr2<new classA>;
ptr2=ptr1; //ptr2所指的对象被delete(自动回收),ptr2指向ptr1原来所指的对象,而ptr1为NULL。
这一性质也导致,一般不将auto_ptr指针作为参数传递给方法,因为进入方法时要复制指针,这就相当于原指针不指向任何东西,而如果方法在最后不将指针返回的话,原对象因为无人指向,因此在方法结束时被删除。因此,如果不是想传递参数,请不要把auto_ptr作为参数或者返回值。
将auto_ptr的引用作为参数传递会使指针的拥有权混乱,因为引用不改变指针的所有权,尽量还是别传引用。
如果不想改变auto_ptr的拥有权,可以把它定义成const,如:
std::auto_ptr<int>f()
{
const std::auto_ptr<int>p(new int);
std::auto_ptr<int>q (new int);
*p =42; //OK 赋值伟42,允许
bad_print(p);  //compile time error ,不能作为参数传递,这样拥有权就变了
*p=*q; //OK ,改变值为0,允许
p=q;   //compile time error ,p不能指向别的地方了
return p;  //compile time error,这一返回,拥有权就变了,不允许
}

 

析构函数只有在构造函数调用成功之后才会被调用,因为如果构造函数运行半途出现异常退出了,不会调用析构函数,很可能造成内存泄漏。如:

class ClassB

{

   private:

    ClassA* ptr1;

    ClassA* ptr2;

   public:

  ClassB (ClassA val1,ClassA val2):ptr1(new ClassA(val1),new ClassA(val2)){}  //如果ptr2(new ClassA(val2))出现异常而退出,就不会调用析构  函 数,因此就会泄漏ptr1所指的对象。

...

 ~ClassB()

{

   delete ptr1;

   delete ptr2;

}

};

 

 

小结一下吧:

1.auto_ptr对象不能共享同一个指针拥有权。

2.不能用于数组,因为它的析构函数不能调用delete[].

3.它不是万能的智能指针,比如它不能用来计数,而share_ptr是干这个的,它允许共享拥有权,会在引用计数为0时自动删除对象。

4.auto_ptr不能作为容器中的element使用。