析构函数不可抛出异常
7.8 ID_throwInDestructor
析构函数抛出异常会违反异常处理机制。
抛出异常后,从 throw 表达式到相应 catch 子句各层调用栈中的对象会被自动析构,如果这个过程中某个对象的析构函数抛出异常便违反了异常处理机制,这种情况将直接引发 std::terminate 函数的执行,所以从析构函数抛出的异常可能无法被捕获和处理,也可能导致程序异常终止。
示例(设 E0 和 E1 是不相关的异常类):
class A {
....
public:
~A() try {
if (cond0) {
throw E0(); // Non-compliant, propagate out
}
else if (cond1) {
throw E1(); // OK, digested by itself
}
}
catch (const E1&) {
....
}
};
建议将析构函数声明为 noexcept。
与析构相关的过程也不应抛出异常:
- 资源回收
- delete、delete[] 运算符
- 具有 deallocate、free 等语义的函数
另外,具有 swap、hash 等语义以及移动构造、移动赋值相关的过程也不应抛出异常,详见相关规则。
相关
依据
ISO/IEC 14882:2003 15.2(3)
ISO/IEC 14882:2011 3.7.4.2(3)-undefined
ISO/IEC 14882:2011 15.2(3)