本篇笔记包含 Term 9~15。

Term 9:利用 destructors 避免泄漏资源

按照 RAII,将资源放入对象当中,通过析构函数可以保证资源被正确回收。通常情况只需要使用智能指针即可,即使发生异常也能保证不出现资源泄露。

Term 10:在 constructors 内阻止资源泄漏(resource leak)

如果构造函数在执行过程中发生异常,可能会出现资源泄露,此时需要捕获异常并处理。简单来说,使用智能指针就好了。

Term 11:禁止异常(exceptions)流出 destructors 之外

  1. 可以避免 terminate 函数在 exception 传播过程的栈展开(stack-unwinding)机制中被调用
  2. 可以协助确保 destructors 完成其应该完成的所有事情

Term 12:了解“抛出一个 exception”与“传递一个参数”或“调用一个虚函数”之间的差异

  1. exception objects 总是会被复制,如果以 by value 方式捕捉,它们甚至被复制两次。至于传递给函数参数的对象则不一定得复制。
  2. “被抛出成为 exceptions”的对象,其被允许的类型转换动作,比“被传递到函数去”的对象少。
  3. catch 子句以其“出现于源代码的顺序”被编译器检验比对,其中第一个匹配成功者便执行;而当我们以某对象调用一个虚函数,被选中执行的是那个“与对象类型最佳吻合”的函数,不论它是不是源代码所列的第一个。
  4. “exceptions 与 catch 子句相匹配”的过程中,仅有两种转换可以发生。第一种是“继承架构中的类转换(inheritance-based conversions)”。第二个允许发生的转换是从一个“有型指针”转为“无型指针”,所以一个针对 const void* 指针而设计的 catch子句,可捕捉任何指针类型的 exception。

Term 13:以 by reference 方式捕捉 exceptions

  1. by pointer 方式捕捉不能保证指针指向有效对象,该对象可能离开作用域就被销毁
  2. by value 方式复制两次效率低下,此外它也会引起切割(slicing)问题,因为 derived class exception objects被捕捉并被视为 base classexceptions 者,将失去其派生成分

Term 14:明智运用 exception specifications

exception specifications 对于“函数希望抛出什么样的 exceptions”提供了卓越的说明。而在“违反 exception specification的下场十分悲惨,以至于需要立刻结束程序”的形势下,它们提供了默认行为。但是虽然有这些好处,它们相对也有一些缺点,包括编译器只对它们做局部性检验、很容易被不经意地违反等。此外它们可能会妨碍更上层的 exception 处理函数处理未预期的 exceptions——即使更上层的处理函数已经知道该怎么做。

Term 15:了解异常处理(exception handling)的成本

异常处理需要额外的成本,需要谨慎决定使用异常处理机制。