析构函数C ++中的exception
我很清楚,不应该在析构函数中抛出任何exception。
但是作为抓住这个概念的一部分,我编码了这个例子:
#include <iostream> using namespace std; class A { private: int i; public: A() { i = 10; } ~A() { throw 30; } }; int main(){ try{ A(); throw 10; } catch (int i){ cout << i << endl; cout << "exception caught" << endl; } }
根据我的理解,这个程序应该通过调用std :: terminate()来终止,因为同时会有两个exception。 但是,这个程序是给出以下输出:
30 exception caught
任何人都可以请解释这背后的逻辑为什么这不是终止?
如果在堆栈展开期间引发exception, std::terminate
将被调用。 这意味着,如果在处理另一个exception时调用exception ,则将调用std::terminate
。
在你的例子中,这不会发生 – A();
将构build并立即销毁 A
一个实例。 throw 30
将被正确地抓住。
将您的代码更改为:
int main(){ try{ A a; // begin `a` lifetime throw 10; // | throw #0 // | end `a` lifetime // throw #1 } catch(int i){ cout<<i<<endl; cout<<"exception caught"<<endl; } }
将保证std::terminate
将被调用。 在这种情况下, a
将被销毁,并在处理另一个exception时抛出。
活的coliru例子
附加信息:
-
cppreference /parsing器/exception
-
StackOverflow:“从析构函数中抛出exception”
请注意, 在C ++ 11及更高版本中 ,您的代码片段将调用std::terminate
并提供警告:
main.cpp:在析构函数A ::〜A()中:
main.cpp:16:15:warning:throw将始终调用terminate()[-Wterminate]
throw 30; ^~
main.cpp:16:15:注意: 在C ++ 11中,析构函数默认为noexcept
抛出'int'实例后终止调用
bash:第7行:1505 Aborted(核心转储).a.out
正如在编译器输出中看到的那样,因为C ++ 11的析构函数隐含地是noexcept(true)
。 如果你想防止这种行为,你可以简单地将它们标记为noexcept(false)
。 例:
~A() noexcept(false) { throw 30; }
在coliru生活的例子
在你的例子中, A()
为A
构造一个临时variables,然后立即破坏它。 这样throw 10;
永远不会执行。
throw
语句发生在A
的析构函数中。 当执行A::~A()
,程序不会退出(即从exception中清除状态)。 例如请参阅“破坏者” 。