I have read several articles here and else where that it is OK to throw exception from constructor. However, I have noticed that it doesn't call destructor of base class or its data members if an exception is thrown from the constructor. Consider the following example:
#include <iostream>
using namespace std;
struct C
{
C() { cout << __FUNCTION__ << endl; }
~C() { cout << __FUNCTION__ << endl; }
};
struct E: public C
{
C c;
E() { cout << __FUNCTION__ << endl; throw 4; }
~E() { cout << __FUNCTION__ << endl; }
};
int main()
{
E e;
}
$ g++ test.cpp; ./a.exe
C
C
E
terminate called after throwing an instance of 'int'
Aborted (core dumped)
In this case, E's constructor throws an exception but C's destructor as a data member or as a base class is not called. Now if C's destructor performs some cleanup operation like closing files/sockets and deleting heap allocations, this can cause problems.
So my question is why and when is it OK to throw exceptions from constructors.
If you catch the error, the destructor will be run. When an uncaught exception is thrown in C++, the runtime calls std::terminate
. By default, std::terminate
calls std::abort
which specifically does not call destructors on the way out.
With this version:
#include <iostream>
using namespace std;
struct C
{
C() { cout << __FUNCTION__ << endl; }
~C() { cout << __FUNCTION__ << endl; }
};
struct E: public C
{
C c;
E() { cout << __FUNCTION__ << endl; throw 4; }
~E() { cout << __FUNCTION__ << endl; }
};
int main()
{
try {
E e;
} catch(...) {
}
return 0;
}
I get output:
C
C
E
~C
~C
I have noticed that it doesn't call destructor of base class or its data members if an exception is thrown from the constructor
Yes, it does.
However, since you don't catch
that exception in the entire program, the program is immediately terminated.
If you were to catch the exception somewhere higher up the call stack, then the destructors of base class and members would be invoked as expected.
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