I am well aware of the fact that one should not throw any exception in destructor.
But as a part of making my grip on this concept,I coded this example :-
#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;
}
}
As per my understanding, this program should be terminated by calling std::terminate() as there will be two exceptions at the same time. But, this program is giving the following output:-
30
exception caught
Can anyone please explain me the logic behind this as to why this is not terminating?
std::terminate
will be called if an exception is thrown during stack unwinding. That means that if an exception is called while another exception is being handled, then std::terminate
will be called.
In your example, that doesn't happen - A();
will construct and immediately destroy an instance of A
. The throw 30
will then be caught correctly.
Changing your code to:
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;
}
}
will guarantee that std::terminate
will be called. In this case, a
will be destroyed and will throw while another exception is being handled.
live coliru example
Additional information:
cppreference/Destructors/Exceptions
StackOverflow: "throwing exceptions out of a destructor"
Note that in C++11 and above, your code snippet will call std::terminate
and provide you a warning:
main.cpp: In destructor ‘A::~A()’:
main.cpp:16:15: warning: throw will always call terminate() [-Wterminate]
throw 30; ^~
main.cpp:16:15: note: in C++11 destructors default to noexcept
terminate called after throwing an instance of 'int'
bash: line 7: 1505 Aborted (core dumped) ./a.out
As seen in the compiler output, since C++11 destructors are implicitly noexcept(true)
. If you want to prevent this behavior, you can simply mark them as noexcept(false)
. Example:
~A() noexcept(false)
{
throw 30;
}
live example on coliru
In your example, A()
construct a temporary variable for A
then destructs it immediately. Thus throw 10;
is never executed.
The throw
statement taking place is in the destructor for A
. When executing A::~A()
, the program is not unwinding (i.e. cleaning up state from an exception) at that point. See "Destructors that throw" for example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With