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:
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.