auto_ptr介绍


#include<memory>

1.C++程序设计的时候,经常会遇到的问题就是,new 与delete的合理调用。内存泄露的问题是很让人都疼的,对于内存泄露的预防通常又会使得代码异常复杂,易错。如以下的一个例子:

   void fun()
   {
 classa * ptr=new classa;
 try{
 
   ...
 }
 catch(...){
   delte ptr;
   return ; 

 }
 delete ptr;
 return;
    }
为了处理指针,而是代码变得非常的复杂,实非我愿。
这里我们可以运用 smart pointer名为 auto_ptr 的Class 来解决这个问题。
那auto_ptr到底指的是什么呢?设计auto_ptr是作为object的owner而存在的,所以当auto_ptr自身被销毁的时候,它的“财产”(也即它所指向的对象就会被销毁,人都没了,财产也没意义了)也会被自动销毁,而通常运用auto_ptr是局部的变量,自然在局部变量的生存期后相应的资源就会被释放。
使用auto_ptr的一个要求是:被指向的object只有一个owner(这里的意思是说,一个object不能被2个或更多的auto_ptr所拥有,但是,坑爹的是语法上同时被多个auto_ptr拥有是没有错误的,需要程序员自己注意!)。好了,我们就用auto_ptr来修改上面的代码吧。
     void fun()
     {
       std::auto_ptr<classa> ptr(new classa);//ok
       std::auto_ptr<classa> ptr=new classa;//error,不能者样构造,原因在于这样new产生的                                            //指针是一个普通的指针,而不是auto_ptr。
       ....
     }
  auto_ptr指针也可以使用普通指针的一些功能,如提领操作符*,->等,但是不能使用++,另外从上面的修改后的例子中,我们也可以看到,auto_ptr不能使用如上的new构造(assignment syntax),但是却可以使用赋值操作(在后面将会提到的)。


2.Transfer of auto_ptr

  auto_ptr之间也可以进行赋值操作,但是我们要记住,无论是什么时候的赋值。都代表着ownership的transfer。比如下面的例子。
 std::auto_ptr<classa> ptr1(new classa);
        std::auto_ptr<classa> ptr2;
 ptr2=ptr1;这里在调用了赋值语句后,ptr2拥有了新建对象的ownership,而ptr1则丢掉了ownership(我想着是跟普通指针的最大区别吧!)
 当然了我们也可以掉用复制构造函数来对auto_ptr进行初始化,如下面的操作:
 std::auto_ptr<classa> ptr1(new classa);
 std::auto_ptr<classa> ptr2(ptr1);
        同样的结果,ptr2拥有了ownership而ptr1丢失了ownership(当然也就指向了NULL啦!)
  如果是auto_ptr已经有了“财产”,再进行赋值语句,那么它之前的财产就会被丢弃掉(被析构掉)。如下代码:
 std::auto_ptr<classa> ptr1(new classa);
 std::auto_ptr<classa> ptr2(new classa);
 ptr2=ptr1;//ptr1之前拥有的object就会马上被析构掉

   
指针作为函数的参数被传递也非常普遍发生的事,但是对于auto_ptr来说,将auto_ptr作为参数传递时,它拥有的“财产”也将会被转移(挺悲催的吧!)给函数的形参(与我们上述的几种情况是吻合的)。但是由于形参是函数局部的,因此随着形参的灭亡,它的“财产”也会被无情的没收了。当然了,我们也可以通过return auto_ptr的方法将“财产”的归属权转移出去,让我们看看如下的例子

 std::auto_ptr<classa> f()
 {
      std::auto_ptr<classa> ptr(new classa);
             ....
      return ptr;
 }

 void g()
 {
      std::auto_ptr<classa> p(new classa);
             for(int i=0;i<5;i++)
      {
  p=f();//这里在反复的调用中,前面赋给P的值析构掉(与上文所述吻合)
  .....
      } 
 }//最后的一个object在P被析构的时候也析构了

我们需要注意的时候,无论何时auto_ptr的使用都带着鲜明的ownership色彩,因此我们在使用auto_ptr作为参数时一定要小心。
       比如说,如果我们将一个auto_ptr作为参数传给了一个函数,那么在函数结束后对应的object就会被析构掉,如果这是我们再使用* ptr的话,就会出现错误。
       另外,我们还可以使用const关键词,const std::auto_ptr<classa> ptr1(new classa);
此时如果使用下面的语句将会报错: ptr2=ptr1,此时财产的转换时不被允许的,但是财产的增减还是允许的,如*ptr=一个新值。总结一句话,就是const修饰后,主人不能变,但是财产时可变的。const修饰的auto_ptr变量也不可以作为参数传递给函数调用。
        非const auto_ptr可以做为参数传递,也分两种情况如下所示
 首先:
 template<class T>
 void fun(const const auto_ptr<T>& p)//;这种情况下的实参不会丢失ownership
                                              //原因是引用没有赋值操作
        如果fun()参数表中不是引用,则显然实参会丢掉ownership

3.auto_ptr作为class成员
    只有在构造函数成功的情况下,才会调用析构函数,因此如果构造函数调用失败而已经分配了内存,将会出现内存泄露的情况,这里只是针对new 分配的内存,其他的栈分配的内存会自动析构,而new 分配的heap内存由于没有调用delete就泄露了。
    作为Class成员最大的好处就在于,如果对象在构造的时候除了问题而没有构造成功,那么已经分配的内存将能够很好的清理掉。原因在于auto_ptr类会析构掉,所以内存也就被处理掉了。

 

警告:
 
 auto_ptr不能作为数组元素而存在,应为其不满足基本的等价原则(前任的将会丢掉财产)。
 不能作为container的元素而存在。

 

 

 

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值