《Effective C++》学习笔记条款13 以对象管理资源

 

条款 13 :以对象管理资源

     

 

例:
    
 voidf()
     {
 
         Investment *pInv = createInvestment();
 
         ...                 
 //这里存在诸多不定因素,可能造成delete pInv;得不到执行,这可能就存在潜在的内存泄露。
         delete pInv;
     }
 


   
 解决方法:把资源放进对象内,我们便可依赖C++析构函数自动调用机制确保资源被释放。
   
 许多资源被动态分配于堆内而后被用于单一区块或函数内。它们应该在控制流离开那个区块或函数时被释放。标准

程序库提供的auto_ptr正是针对这种形势而设计的特制产品。auto_ptr是个类指针对象,也就是所谓的智能指针

其析构函数自动对其所指对象调用delete

    void f()
     {
 
        std::auto_ptr<Investment> pInv(createInvestment()); 
         ...
 
     }
         //函数退出,auto_ptr调用析构函数自动调用delete,删除pInv无需显示调用delete
   
 

     “以对象管理资源两个关键想法

  • 获得资源后立刻放进管理对象内(如auto_ptr)。每一笔资源都在获得的同时立刻被放进管理对象中。“资源取得时机便是初始化时机”(Resource Acquisition Is Initialization;RAII)。
  • 管理对象运用析构函数确保资源被释放。即一旦对象被销毁,其析构函数被自动调用来释放资源。

        由于auto_ptr被销毁时会自动删除它所指之物,所以不能让多个auto_ptr同时指向同一对象。所以auto_ptr若通

copying函数复制它们,它们会变成NULL,而复制所得的指针将取得资源的唯一拥有权!
   
 

看下面例子:
   
 

     std::auto_ptr<Investment> pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
    
 std::auto_ptr<Investment>pInv2(pInv1);                     //现在pInv2指向对象,而pInv1被设为NULL;

     pInv1 = pInv2;                                                           //现在pInv1指向对象,而pIn2被设为NULL;
   
 

      受auto_ptr管理的资源必须绝对没有一个以上的auto_ptr同时指向它有你没我,有我没你
  
    auto_ptr的替代方案是引用计数型智能指针reference-counting smart pointerSCSP)、它可以持续跟踪共有

多少对象指向某笔资源,并在无人指向它时自动删除该资源。

    TR1tr1::shared_ptr就是一个"引用计数型智能指针"
     void f()
     {
 
         ...
 
        std::tr1::shared_ptr<Investment>  pInv1(createInvestment()); //pInv1指向createInvestment()返回物;
        std::tr1::shared_ptr<Investment> pInv2(pInv1);                    //pInv1pInv2指向同一个对象;
         pInv1 = pInv2;                                                                    
 //同上,无变化
         ...
 
     }
        //函数退出,pInv1pInv2被销毁,它们所指的对象也竟被自动释放。
   
    
auto_ptrtr1::shared_ptr都在其析构函数内做delete而不是delete[],也就意味着在动态分配而得的数组身上使

auto_ptrtr1::shared_ptr是个潜在危险,资源得不到释放。也许boost::scoped_arrayboost::shared_array能提供

帮助。还有,vectorstring几乎总是可以取代动态分配而得的数组。

    请记住:

  • 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源。
  • 两个常被使用的RAII类分别是auto_ptr和tr1::shared_ptr。后者通常是较佳选择,因为其拷贝行为比较直观。若选择auto_ptr,复制动作会使他(被复制物)指向NULL。   

 

posted on 2013-12-16 12:48  我的小人生  阅读(186)  评论(0编辑  收藏  举报