1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include <cstdio>
struct A { ~A() { puts("~A()"); throw 0; } };
int main() { try { A(); puts("after ~A()"); } catch (...) { puts("catch"); } }
|
分别用C++98和11标准进行编译及运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ g++ examples/destructor-throw.cpp -std=c++98 && ./a.out ~A() catch $ g++ examples/destructor-throw.cpp -std=c++11 && ./a.out examples/destructor-throw.cpp:6:9: warning: '~A' has a non-throwing exception specification but can still throw [-Wexceptions] throw 0; ^ examples/destructor-throw.cpp:4:5: note: destructor has a implicit non-throwing exception specification ~A() { ^ 1 warning generated. ~A() libc++abi: terminating with uncaught exception of type int Abort trap: 6
|
开启C++11标准后,编译器已经给出了警告。实际上,C++11起,析构函数默认是noexcept的,抛出异常将会terminate。
做一点修改,再次编译
1 2 3 4 5 6 7 8
| #include <cstdio>
struct A { - ~A() { + ~A() throw(int) { puts("~A()"); throw 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12
| $ g++ examples/destructor-throw.cpp -std=c++11 && ./a.out ~A() catch $ g++ examples/destructor-throw.cpp -std=c++17 && ./a.out examples/destructor-throw.cpp:4:10: fatal error: ISO C++17 does not allow dynamic exception specifications [-Wdynamic-exception-spec] ~A() throw(int) { ^~~~~~~~~~ examples/destructor-throw.cpp:4:10: note: use 'noexcept(false)' instead ~A() throw(int) { ^~~~~~~~~~ noexcept(false) 1 error generated.
|
给析构函数添加动态异常说明后,程序不会崩溃。要注意的是,动态异常说明在C++11中标记为弃用,C++17起已经移除了。
总结:不要把异常抛出析构函数。