Effective C++(13) 用对象管理资源

2014-11-24 07:33:40 · 作者: · 浏览: 0
问题聚焦:
从这条准则开始,都是关于资源管理的。
资源,一旦用了它,将来必须还给 系统
本条准则,基于对象的资源管理办法,建立在C++的构造函数,析构函数和拷贝函数(拷贝构造函数和重载赋值操作符)的基础上。


Demo: root class Investment:
class Investment { ... };
// 工厂函数
Investment* createInvestment();   // 返回指向一个Investment或者其子类的对象,调用者有责任删除它

// 考虑如下调用
void f() 
{
    Investment* pInv = createInvestment();
    ......
    delete pInv;      // 释放pInv所指的对象
}

问题:
当在delete语句调用之前出现return语句或者抛出异常并且该异常被默默地忽略掉时,这个对象便无法被释放。
解决思路:
C++的析构函数自动调用机制
方案一:类指针对象
标准程序库提供的 auto_ptr 是个“类指针对象”,也就是所谓的智能指针,其析构函数自动对所指对象调用delete。
void f()
{
    std::auto_ptr
  
    pInv(createInvestment(( ));
    ......
}
  

关键:
获得资源后立刻放进管理对象:资源取得时机便是初始化时机 管理对象运用析构函数确保资源被释放:一旦对象被销毁(例如当对象离开作用域),其析构函数自然会被自动调用,于是资源被释放。
性质:唯一拥有权。
为了防止多个auto_ptr同时指向同一对象,auto_ptr有一个不同寻常的性质:若通过拷贝构造函数或重载赋值操作符复制它们,原指针会变成null,而复制所得的指针将取得资源的唯一拥有权。
void f()
{
    std::auto_ptr
  
    pInv(createInvestment(( ));
    ......
}
  

方案二:引用计数型智慧指针RCSP 思想:持续追踪共有多少对象指向某笔资源,并在无人指向它时自动删除该资源。
void f()
{
    ...
    std::str1::shared_ptr
  
    pInv(createInvestment());
    ...
}
  

区别:str1::shared_ptr的调用和auto_ptr相同,区别就是在复制行为上
void f()
{ 
    ......
    std::tr1::shared_ptr
  
    pInv1(createInvestment());
    std::str1::shared_ptr
   
     pInv2(pInv1); // pInv1和pInv2指向同一对象 pInv1 = pInv2; }
   
  

需要格外注意下面这种错误用法:
std::auto_ptr
  
    aps(new std::string[10]);
std::str1::shared_ptr
   
     spi(new int[1024]);
   
  

错误原因:auto_ptr和str1::shared_ptr两者在其析构函数内做delete而不是delete[]动作。
格外指出:createInvestment返回”未加工指针“是个非常不好的接口设计,在后面的条款中会对这个接口进行修改。

小结:
为了防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源 两个常被使用的RAIIclasses分别是tr1::shared_ptr和auto_ptr,前者通常是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它指向Null。

参考资料: 《Effective C++ 3rd》