More Effective C++ 条款11 禁止异常流出destructor之外
1. ”两种情况下destructor会被调用。第一种情况是当对象在正常情况下被销毁,也就是当它离开了它的生存空间或是被明确的删除;第二种情况是当对象被exception处理机制——也就是exception传播过程中的stack-unwinding(栈展开)机制——销毁。”
2. 当destructor被调用时,可能(也可能不)有一个exception正在作用之中,但我们无法再destructor中区分这些状态(现在有了区分的办法。1995年7月 IOS/ANSI C++ 标准委员会加入一个新函数: uncaught_exception。如果某个exception正在作用中而尚未被捕捉的话,它会返回true)。当destructor抛出一个异常的时候而不会被destructor捕捉的时候,它会传播到destructor的调用端,如果这个destructor本身是因他某个exception而被调用的,terminate函数便会被调用,它默认调用abort函数终止程序。
3. 对于2有一个解决办法可以防止destructor抛出的异常传出destructor之外,那就是将destructor函数体包在一个try块之中,而catch(...)语句什么也不做,示例代码如下:
1 ~A(){ 2 try{ 3 ... 4 } 5 catch(...){} 6 } 7 //......代表中间的代码被省略,...代表C++的元运算符
4. 除了2所示原因,让exception传出destructor之外还有一个坏处:如果destructor抛出exception而没有在当地捕捉,那个destructor就是执行不全,也就是说它没有完成它应该完成的事情。
5. 综上,有两个理由支持我们采取措施阻止exception传出destructor之外:第一,它可以避免terminate函数在exception传播过程中的栈展开(stacking-unwinding)机制中被调用;第二,它可以协助确保destructors完成其应该完成的所有事情。