Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructor called after throwing from a constructor

I used to think that in C++, if a constructor throws an exception, the destructor of this "partially constructed" class is not called.

But it seems that it is not true anymore in C++11: I compiled the following code with g++ and it prints "X destructor" to the console. Why is this?

#include <exception> #include <iostream> #include <stdexcept> using namespace std;  class X { public:     X() : X(10)     {         throw runtime_error("Exception thrown in X::X()");         }     X(int a)     {         cout << "X::X(" << a << ")" << endl;     }     ~X()     {         cout << "X destructor" << endl;     } };  int main() {     try     {         X x;     }     catch(const exception& e)     {         cerr << "*** ERROR: " << e.what() << endl;     } } 

Output

Standard out: X::X(10)  X destructor Standard error:  *** ERROR: Exception thrown in X::X() 
like image 505
Mr.C64 Avatar asked Jan 17 '13 19:01

Mr.C64


People also ask

Is destructor called on throw?

Yes, destructors are guaranteed to be called on stack unwinding, including unwinding due to exception being thrown. There are only few tricks with exceptions that you have to remember: Destructor of the class is not called if exception is thrown in its constructor.

Is destructor called after return?

While returning from a function, destructor is the last method to be executed. The destructor for the object “ob” is called after the value of i is copied to the return value of the function. So, before destructor could change the value of i to 10, the current value of i gets copied & hence the output is i = 3.

Is destructor called after move?

uninitialized_move() initializes new T objects into the new memory area by moving them from the old memory area. Then it calls the destructor on the original T object, the moved-from object.

Can destructor be called without constructor?

Yes, the destructor is nothing more than a function. You can call it at any time. However, calling it without a matching constructor is a bad idea.


1 Answers

Delegating constuctors are indeed a new feature that introduces a new destruction logic.

Let us revisit the lifetime of an object: An object's lifetime begins when some constructor has finished. (See 15.2/2. The standard calls this the "principal constructor".) In your case, this is the constructor X(int). The second, delegating constructor X() acts as just a plain member function now. Upon scope unwinding, the destructors of all fully-constructed objects are called, and this includes x.

The implications of this are actually quite profound: You can now put "complex" work loads into a constructor and take full advantage of the usual exception propagation, as long as you make your constructor delegate to another constructor. Such a design can obviate the need for various "init"-functions that used to be popular whenever it wasn't desired to put too much work into a regular constructor.

The specific language that defines the behaviour you're seeing is:

[C++11: 15.2/2]: [..] Similarly, if the non-delegating constructor for an object has completed execution and a delegating constructor for that object exits with an exception, the object’s destructor will be invoked. [..]

like image 187
Kerrek SB Avatar answered Sep 22 '22 06:09

Kerrek SB