《Effective C++》资源管理章节
Item 13:以对象管理资源
关键的两个想法(这种方式其实在很多地方都可以看出影子,比如managing pool的模型):
1.获得资源后立刻放入管理对象(managing object):以对象管理资源的观念常常被称为“资源取得之时就是初始化时机”(Resourece Acquisition Is Initialization;RAII),因为我们总是在获得资源后,在同一语句内用它来初始化某个管理对象。有时候获得的资源被拿来赋值(而非初始化)某个管理对象。但不管哪一种做法,每一笔资源都在获得的同时立刻被放入管理对象中。
2.管理对象(managing object)运用析构函数确保资源被释放:不管控制流如何离开区域块,一旦对象被销毁(例如当对象离开作用域时),其析构函数自然会被自动调用,于是资源被释放。如果资源释放动作可能抛出异常,事情就变的有些棘手了(可以参考item8)。
总结:
1.为防止泄漏资源,请使用RAII对象,它们在构造函数中获得资源并且在析构函数中释放资源。
2.两个常被使用的RAII classes是shared_ptr和auto_ptr。前者通常是最佳选择,因为其copy行为比较直观。若选择auto_ptr,复制动作会使它(被复制物)指向null。
Item 14:在资源管理类中要小心copying行为
对于那些并不是在heap-based的资源,采用auto_ptr,shared_ptr并不是一个好方法,这时候我们需要自己建立一个管理类,这时候我们就会面临一个问题:“当一个RAII class被复制时候,我们要怎么选择?”
1.禁止复制。如Item6中告诉我们的,可以将赋值构造函数和操作符设置为private:
class Lock
{
private:
void operator=(){};
Lock(const Lock&){};
}
2.对底层资源使用“引用计数法”。有时候我们希望保有资源,直到它的最后一个使用者(某对象)被销毁。这种情况下复制RAII对象,应该将该资源的count变量+1,shared_ptr就是如此。
3.复制底部资源。
4.转移底部资源控制权。这一条就是auto_ptr所奉行的复制意义。
总结:
1.复制RAII对象必须一并复制它所管理的资源,所以资源的copying行为决定RAII对象的copying行为。
2.普遍而常见的RAII class copying行为是:抑制copying、实施引用计数法。不过其他的行为也可能被实现。
Item15:在资源管理类中提供对原始资源的访问
总结:
1.APIs往往要求访问原始资源,所以每一个RAII class应该提供一个“取得其管理的资源的方法”。
2.对原始资源的访问可能经由显式或者隐式转换。一般而言显式转换比较安全,但隐式转换对客户比较方便。
Item16:成对使用new和delete时要采取相同的形式
总结:如果你在new表达式中使用了[],必须在相对应的delete表达式中也使用[]。如果你在new的表达式中没有使用[],一定不要在相应的delete表达式中使用[]。
(不管是哪一种情况搞反了,都会导致未定义的结果)
Item17:以独立语句将newed对象置入智能指针
总结:以独立语句将newed对象存储于智能指针中。如果不这么做,一旦异常被抛出,有可能导致难以察觉的内存泄漏。