Destructor called after throwing from the 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 looks like this is no longer the case in C ++ 11: I compiled the following code with g ++, and it prints an β€œ 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; } } 

Exit

 Standard out: X::X(10) X destructor Standard error: *** ERROR: Exception thrown in X::X() 
+69
c ++ exception c ++ 11
Jan 17 '13 at 19:43
source share
2 answers

Delegating conductors are truly a new feature that introduces new destruction logic.

Let us return to the lifetime of the object: the lifetime of the object begins when any constructor is completed. (See 15.2 / 2. The standard calls this the "main constructor".) In your case, this is the X(int) constructor. The second delegating constructor, X() , now acts as a simple member function. When a region is expanded, 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” workloads into the constructor and make full use of the usual exception propagation if you pass your constructor to another constructor. Such a construction can eliminate the need for various "init" functions that were previously popular when you did not want to work too much in the regular constructor.

The specific language that defines the behavior that you see:

[C++11: 15.2/2]: [..] Similarly, if the constructor without delegation for an object completes execution, and the delegation constructor for this object exits with an exception, the object destructor will be called. [..]

+78
Jan 17 '13 at 19:45
source share

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 like this is not the case in C ++ 11

This is still the case. Nothing has changed since C ++ 03 (for some value, nothing ;-))

That, in your opinion, is still true, but there is no partial object when an exception is thrown.

The C ++ 03 standard TC1 says (focus):

An object, partially constructed or partially destroyed, will have destructors executed for all its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet started execution.

i.e. Any object that completed its constructor will be destroyed by executing the destructor. This is a simple rule.

Basically, the same rule applies in C ++ 11: as soon as X(int) returns, the constructor object has completed execution, therefore it is completely constructed and therefore its destructor will work at the appropriate time (when it goes beyond the scope or exception arises at some later stage of its construction.) Still the same rule.

The body of the delegation constructor is executed after another constructor and can do additional work, but this does not change the fact that the construction of the object is completed, therefore it is completely built. The delegation constructor is similar to the constructor of a derived class, which executes more code after the constructor of the base class completes. In a sense, you can consider your example like this:

 class X { public: X(int a) { cout << "X::X(" << a << ")" << endl; } ~X() { cout << "X destructor" << endl; } }; class X_delegating : X { public: X_delegating() : X(10) { throw runtime_error("Exception thrown in X::X()"); } }; 

This is not entirely true, there is only one type, but it is similar to the X(int) constructor, then additional code is run in the delegation constructor, and if it returns X "base class" (which is not really the base class) is destroyed .

+24
Jan 18 '13 at 0:06 on
source share



All Articles