<异常>
条款9:利用destructors避免泄露资源
在函数中,可以将资源封装在局部对象中,通常便可以在exceptions出现时避免泄露资源。是因为局部对象总是会在函数结束时被析构,不论函数如何结束,但唯一例外的就是调用longjmp而结束。
条款10:在constructors内阻止资源泄露(resource leak)
C++只会析构已构造完成的对象。对象只有在其constructor执行完毕才算是完全构造妥当。
面对尚未完全构造好的对象,为什么C++拒绝调用其析构函数?是因为若析构函数被调用于一个尚未完全的构造好的对象身上,那么这个析构函数如何知道构造函数现在构造了那些资源?若添加变量来统计资料的构造程度,将造成效率的降低。
条款11:禁止异常(exceptions)流出destructors之外
在两种情况下,析构函数会被调用:
有两个理由支持我们全力阻止exceptions传出destructors之外:
条款12:了解抛出一个exception与传递一个参数或调用一个虚函数之间的差异
函数参数和exceptions的传递方式有三种:by value、by reference、by pointer。但是需要注意两者的不同,是因为如果你调用一个函数,控制权最终会回到调用端(除非失败以至于无法返回),但是当你抛出一个exception,控制权不会再回到抛出端。
exceptions与catch字句匹配的过程中,仅有两种转换可以发生:
传递对象到函数或是以对象调用虚函数和将对象抛出成为一个exception之间的差异:
条款13:以by reference方式捕捉exceptions
catch-by-pointer方式是唯一在搬移异常相关信息时不需要拷贝对象的一种做法。它有两种做法:
catch-by-value方式:当异常对象被抛出时,就的拷贝两次。同时它可能印发对象切割问题。因为derived class exception objects被捕捉并被视为base class exceptions者,将失去其派生成分(参考《深入探索C++对象模型》)。
catch-by-reference方式:它不像catch-by-pointer,不会发送对象删除问题,因此也就不难捕捉标准的异常;它也不想catch-by-value,没有切割问题,而且异常只会被拷贝一次。
条款14:明智运用exception specifications
如果函数抛出一个未列于其exception specification的exception,这个错误将会在运行期被检测出来,于是特殊函数unexpected会被自动调用。其中,unexpected函数的缺省行为是调用terminate函数,而terminate函数的缺省行为是调用abort函数,因此程序如果违反exception specification,缺省结果就是程序被中断。
避免踏上unexpected之路的方法:
C++允许你以不同型别的exceptions取代非预期的exceptions。
条款15:了解异常处理(exception handling)的成本
为了能够在运行期处理exceptions,程序必须做大量的簿记工作。在每一个执行点,它们必须能够确认如果发送exception,哪些对象需要析构;它们必须在每一个try语句块的进入点和离开点做记号;针对每个try语句块它们必须记录对应的catch子句以及能够处理的exceptions型别。
PS. 这里只是一个大体,如果想要了解更多的知识或者更好的运用,需要看《More effective C++》一书中对异常的具体条款描述。