3 资源管理
所谓资源就是,一旦用了它,将来必须还给系统。
条款13:以对象管理资源。
有时仅仅用delete语句释放资源是行不通的,因为可能程序根本不会执行到delete语句。
我们可以把资源放进对象内,我们便可以依赖c++的“析构函数自动调用机制”确保资源被释放。
auto_ptr是个“类指针对象”,也就是所谓的“智能指针”,其析构函数自动对其所指对象调用delete。
由于auto_ptr被销毁时会自动删除它所指之物,所以一定要注意别让多个auto_ptr同时指向同一对象。为预防这个问题,auto_ptr有一个不寻常的性质:若通过copy构造函数或copy assignment操作符复制它们,它们会变成null,而复制所得的指针将取得资源的唯一拥有权!
auto_ptr的替代方案是“引用计数型智慧指针”。所谓RCSP(reference-couting smart pointer;)也是一个智能指针,持续追踪共有多少个对象指向某笔资源,并在无人指向它时自动删除该资源。
上面的两种管理都不用于“C++动态分配数组”delete [];因为vector和string几乎总是可以取代动态分配而得的数组。
请记住:
n 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源,并在析构函数众所释放资源;
n 两个常被使用RAII classes 分别是tr1::shared_ptr和auto_ptr。前者通常是较佳选择,因为其copy行为比较直观。若选择auto-ptr,复制动作会使它(被复制物)指向null。
条款14:在资源管理类中小心coping行为。
当一个RII对象被复制时,可能会发生两个使用者同时使用一个资源的情况,所以:
n 禁止复制,如条款06;
n 对底层资源祭出“引用计数法”,如tr1::shared_ptr;
n 复制底部资源,深度拷贝,在赋值资源管理对象,,应该同时也赋值其所包覆的资源。
n 转移底部资源的拥有权:永远只有一个RAII对象指向一个未加工资源,如auto_ptr;
条款15:在资源管理类中提供对原始资源的访问。
有些APIs直接访问原始资源如:
你想要这么调用它:
int days = daysHeld(pInv);
却通不过编译,因为daysHeld需要的是Investment*指针,你传给它的却是个类型为tr1::shared_ptr<Investment>的对象。
这时候你需要一个函数可将RAII class对象转换为其所含之原始资源。有两个做法可以达成目标:显示转换和隐式转换。
显示转换:提供一个get成员函数,返回智能指针内部的元素指针:
int days = daysHeld(pInv.get());
隐式转换:就像所有智能指针一样tr1::shared_ptr和auto_ptr也重载了operator ->和operator *,它们允许隐式转换至底部原始指针,还有提供隐式转换函数:
请参见c++ primer14.9节
条款16:成对使用new和delete时要采取相同形式。
请记住:
如果你在new表达式中使用[],必须在相应的delete表达式中也使用[]。如果你在new表达式中不使用[],一定不要在相应的delete表达式中使用[]。
条款17:以独立语句将newed对象置入智能指针。
请记住:
以独立语句将newed对象存储于(置入)智能指针内。如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄漏。