条款 13:以对象管理资源
- 在使用 new 和 delete 之间,可能因为有跳转语句,或者因为中间有异常,而导致执行不到 delete。
- 为了防止资源泄露,应该使用 RAII 对象,它们在构造函数中获得资源,并在析构函数中释放资源。
- 获得资源后立刻放进管理对象中。【RAII:资源取得时机便是初始化时机】
- 管理对象运用析构函数确保资源被释放,不论控制流如何离开区块,一旦对象被销毁(例如当对象离开作用域),其析构函数会自动调用,于是资源被释放。
- 两个 RAII class 是
auto_ptr
和trl::shared_ptr
。【auto_ptr
问题也很多,被unique_ptr
替代】auto_ptr
的复制行为会使被复制物指向空。- 使用
shared_ptr
保存工厂函数所返回的结果。
条款 14:在资源管理类中小心 copying 行为
- 复制 RAII 对象必须一并复制它所管理的资源,并以资源的 copying 行为决定 RAII 对象的 copying 行为。
- 当一个 RAII class 被复制的时候,一般有两种选择:
- 禁止复制。(如条款 6 所说,将 copying 置为 private)
- 引用计数法。(添加 shared_ptr 进行管理)
条款 15:在资源管理类中提供对原始资源的访问
- API 往往要求访问原始资源,所以每一个 RAII class 应该提供一个取得其所管理资源的方法。
- 对原始资源的访问有两种方式:
- 显式:在 RAII class 中保存原资源,然后调用一个成员函数取得它。
- 隐式:重载转换操作符,但是隐式转换容易出错误。
条款 16:成对使用 new 和 delete 要采用相同的形式
- new 和 delete、new[] 和 delete[] 必须成对出现,不然会出现差错。
- 但是要注意习惯用 typedef 的代码,因为可能对一个数组类
B[]
typedef 成另一个名称A
,如果 new 了A
,就相当于调用了 new[],成对出现的必须是 delete[]。
条款 17:将独立语句将 newed 对象置入智能指针中
- 也就是说尽量不要隐式转换地将 newed 对象置入 RAII 类中,如下面的代码就是有问题的:
void A(std::tr1::shared_ptr<B> pw);// 声明 // 现在进行调用: A(new B);
- 首先第一个问题是这里 new 一个对象,最后想要隐式转换成智能指针类;但 shared_ptr 的有参构造是加了 explicit 关键字的,所以阻止了隐式转换,这语句连编译器都不会通过。
- 但即使在调用中显式表明调用构造函数,但仍有另一方面的问题:调用可能会造成资源泄露。
- 简单来说,new 一个对象和将其作为参数调用构造函数是两个步骤,编译器执行的顺序不一致。
- 在资源被创建(new 对象)和资源被转换成资源管理对象之间可能有异常干扰。
- 所以最好以独立语句将 newed 对象置入智能指针中。