Item 13-以对象管理资源(Use objects to manage resources)
半边想法:把资源放进对象内,我们便可依赖C++的"析构函数自动调用机制"确保资源被释放。
许多资源被动态分配与heap内而后被用于单一区域或函数内。它们应该在控制流离开那个区域或函数时被释放。标准程序库提供的auto_ptr正是针对这种形势而设计的特质产品。auto_ptr是个"类指针(pointer-like)对象"也就是所谓"智能指针",其析构函数自动对其所指对象调用detele。
Ex:
class Investment{...}; //"投资类型"继承体系中的root class Investment* createInvestment(); //返回指针,指向Investment继承体系内的动态分配对象。调用者有责任删除它。 void f() { std::auto_ptr<Investment> pInv(createInvestment()); ... } //经由auto_ptr的析构函数自动删除pInv
1、获得资源后立刻放进管理对象内(managing object)内。
f()中,createInvestment返回的资源被当做其管理者auto_ptr的初值。实际上"以对象管理资源"的观念常被称为"资源取得时机便是初始化时机"(Resource Acquisition Is Initialization; RAII),因为我们几乎总是在获得的资源被拿来赋值(而非初始化)某个管理对象,但不论哪一种做法,每一笔资源都在获得的同时立刻被放进管理对象中。
2、管理对象(managing object)运用析构函数确保资源被释放。
由于auto_ptr被销毁时会自动删除它所指之物,所以一定要注意别让多个auto_ptr同时指向同一个对象。不然对象就会删除一次以上。
所以auto_ptr有一个不寻常的性质:若通过copy构造函数或copy assignment操作符复制它们,它们会变成NULL,而复制所得的指针将取得资源的唯一拥有权。
所以,auto_ptr并不是最佳方案。
替代方案"引用计数型智慧指针"(reference-counting smart pointer; RCSP)。RCSP也是个智能指针,持续追踪共有多少对象指向某笔资源,并在无人指向它们时自动删除该资源。
Ex:
void f() { ... std::trl::shared_ptr<Investment> pInv1(createInvestment()); //pInv指向createInvestment返回物理= std::trl::shared_ptr<Investment> pInv2(pInv1); //pInv1和pInv2指向同一个对象 pInv1=pInv2; ... } //pInv1和pInv2都被销毁
为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源。
两个常被使用的RAII classes分别是trl::shared_ptr和auto_ptr。前者是较佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向NULL。