Is the destructor called when a delegating constructor throws? - c++

It is well known that if a constructor throws, then all fully constructed sub-objects will be destroyed in reverse order including member data and all kinds of base classes. The destructor does not get called for non-delegating constructors though. For a delegating constructor the object has been constructed when the constructor body is entered, but construction continues somewhat. Therefore the question arises whether the destructor of the class is called, if the delegating constructor throws an exception from within its body?
class X
{
public:
X();
X(int) : X() { throw std::exception(); } // is ~X() implicitely called?
~X();
};

The rule is that the destructor is called for all fully
constructed objects. The object is considered fully constructed
once any constructor has finished, including the delegated
constructor (even though the program continues in another
constructor).

The lifetime of an object begins when any constructor (i.e., in the
case of delegation, the ultimate target constructor) is successfully
completed. For the purposes of [C++03] §3.8, “the constructor call
has completed” means any constructor call. This means that an
exception thrown from the body of a delegating constructor will cause
the destructor to be invoked automatically.
source.
And here is a nice article about delegating constructors, should anybody want to read it.

Related

Are non-static class members destroyed even without a destructor?

In Bjarne Stroustrup's "The C++ Programming Language (4th edition)" in section 17.6 (Generating Default Operations) it mentions this:
If the programmer declares a copy operation, a move operation, or a
destructor for a class, no copy operation, move operation, or
destructor is generated for that class.
Thus, I'm confused why the SubObj destructor is called in this program:
#include <iostream>
using namespace std;
class SubObj {
public:
~SubObj() {
cout << "SubObj Destructor called" << endl;
}
};
class Obj {
private:
SubObj so;
public:
Obj() {};
Obj(const Obj& o) {};
};
int main() {
Obj();
cout << "Program end" << endl;
}
When compiling with g++ I get the following output:
$ ./a.out
SubObj Destructor called
Program end
Based on my understanding, I expected the default destructor for Obj to not be auto-generated because I defined a copy operation for Obj. And thus, I expected that the SubObj member of Obj would not be destroyed because there is no destructor for Obj.
Thus, I'm wondering: are object members automatically destroyed even without a destructor? Or is a destructor somehow being auto-generated for this example?
Edit:
Later in the book (17.6.3.4), when referring to an example, Bjarne mentions:
We defined copy assignment, so we must also define the destructor.
That destructor can be =default because all it needs to do is to
ensure that the member pos is destyored, which is what would have
been done anyway had the copy assignment not been defined.
Based on the answers so far, it sounds appears as though Bjarne may have just been wrong on this one.
That phrase from the book is poorly worded/wrong.
Of course a destructor is still generated if you provide a copy constructor. If it weren't, your program would not be able to be compiled.
If you provide your own destructor, a destructor is not generated. It doesn't need to be, and you can't have two.
Also, members are destroyed regardless of what your destructor does. A destructor allows you to do "extra" stuff, on top of the normal rules for object (and subobject) lifetime. There was never a risk that the SubObj member wouldn't be destroyed.
Bjarne's wording could have been better here. What
If the programmer declares a copy operation, a move operation, or a destructor for a class, no copy operation, move operation, or destructor is generated for that class.
Could more accurately be (but is still wrong, see the link below for the full rules)
If the programmer declares a copy operation, a move operation, or a destructor for a class, no copy operation, move operation, or destructor (respectively) is generated for that class.
meaning if you declare any of those special member functions, the compiler will not add it's own version. If you declare a copy constructor, it does not stop the destructor, only the copy constructor (and move in C++11+). Only defining a destructors stops the compiler from generating one. To see all of the rules see: What are all the member-functions created by compiler for a class? Does that happen all the time?
I do not have this book to check what is actually written here, but either you are quoting it incorrectly, or it is inaccurate (the latter is hard to believe). The other option is that it is just poorly phrased and confusing.
The only time when compiler will not generate an implicit destructor is when it is explicit:
If no user-declared destructor is provided for a class type (struct,
class, or union), the compiler will always declare a destructor as an
inline public member of its class.
https://en.cppreference.com/w/cpp/language/destructor

Why is destructor of base class called from noexcept constructor [duplicate]

I have a class with a deleted destructor (in practice, it needs outside help to be destroyed):
struct indestructible {
indestructible(indestructible&&);
~indestructible() = delete;
};
When I try to use its move constructor, the compiler complains:
struct user {
indestructible ind;
user(indestructible&& ind) : ind(std::move(ind)) {}
};
indestructible.cc:11:3: error: attempt to use a deleted function
user(indestructible&& ind) : ind(std::move(ind)) {}
^
indestructible.cc:6:3: note: '~indestructible' has been explicitly marked deleted here
~indestructible() = delete;
What's going on? there are no other members that could throw, and neither does the constructor body, so why is there any cause for the move constructor to invoke the destructor?
When your user object gets out of scope, it is destructed. Its members are destructed, including the indestructible member, and that's impossible since its destructor is deleted.
[class.base.init]/12:
In a non-delegating constructor, the destructor for each direct or
virtual base class and for each non-static data member of class type
is potentially invoked (12.4). [ Note: This provision ensures that
destructors can be called for fully-constructed sub-objects in case an
exception is thrown (15.2). —end note ]
[class.dtor]/11:
A program is ill-formed if a destructor that is potentially invoked is
deleted or not accessible from the context of the invocation.
No exception is made for a constructor that doesn't throw. See also CWG 1915.

Is an object fully constructed at the end of the initialiser list?

This is a spinoff from invoking the copy constructor within the constructor.
I believe that an object is fully formed and can be expected to behave as such by the end of the initialiser list (edit: I was wrong about this though!). Specifically, member functions and accessing local state from within the constructor itself will behave exactly as they would from any other member function.
This seems to be a slightly contentious point of view though, the alternative is that only once the constructor has returned normally is the object fully formed.
The following is a quick & dirty test case for this which shows all the member fields that are mentioned in the initialiser list being initialised and those that aren't getting default constructed.
#include <cstdio>
struct noise
{
noise() { printf("noise default constructed\n"); }
noise(int x) { printf("noise integer constructed %u\n", x); }
~noise() { printf("noise dtor\n"); }
};
struct invoke : public noise
{
noise init;
noise body;
invoke() : noise(3), init(4)
{
body = noise(5);
throw *this; // try to use the object before returning normally
}
~invoke() { printf("invoke dtor\n"); }
};
int main()
{
try
{
invoke i;
}
catch (...)
{
}
}
This prints, on my machine at least,
noise integer constructed 3
noise integer constructed 4
noise default constructed
noise integer constructed 5
noise dtor
noise dtor
noise dtor
noise dtor
invoke dtor
noise dtor
noise dtor
noise dtor
As always, it's difficult to distinguish works-as-specified from works-as-my-compiler-implemented! Is this actually UB?
Is an object fully constructed at the end of the initialiser list?
No it is not. The object this is fully constructed at the end of the execution of the constructor.
However, all the members are constructed by the end of the initializer list.
The difference is subtle but it is important as it relates to the execution of the destructors. Every constructed member and base class is destructed if the this object throws an exception during the execution of the constructor. The destructor of the this object will only execute once it is fully constructed.
From the cppreference:
For any object of class or aggregate types if it, or any of its subobjects, is initialized by anything other than the trivial default constructor, lifetime begins when initialization ends.
For any object of class types whose destructor is not trivial, lifetime ends when the execution of the destructor begins.
Your example is well-defined behavior, but only just so.
To be clear, the "invoke dtor" line we're seeing is from the destruction of your exception, not the top-level i object.
Each member of the class is initialized by the time the constructor body starts, though the object itself is not initialized until the constructor body completes. This is why ~invoke is not called on the top-level invoke object.
The throw *this expression copy-initializes an invoke object from *this, which is allowed. (The standard explicitly states that "Member functions [...] can be called during construction or destruction".) Your copy-initialization is the default, which just copy-initializes all the members - which have all been initialized.
Then because your constructor body is exiting via exception, all the initialized members are destructed, the exception is propagated, caught, and then disposed of, calling ~invoke, and in turn destroying those members as well.

Can objects with private copy constructors be thrown?

I've come across some exceptions issue that is unclear to me. In C++, when an object is thrown it is first copied to a temporary object, and the temporary object is then passed to the catching code. The copy involves the use of the object's class copy constructor. AFAIK, this means that if a class has a private copy constructor, it can't be used as an exception. However, in VS2010, the following code compiles and runs:
class Except
{
Except(const Except& other) { i = 2; }
public:
int i;
Except() : i(1) {}
};
int main()
{
try
{
Except ex1;
throw ex1; // private copy constructor is invoked
}
catch (Except& ex2)
{
assert(ex2.i == 2); // assert doesn't yell - ex2.i is indeed 2
}
return 0;
}
Is this legal?
It's not legal. Standard 15.1/5
If the use of the temporary object can be eliminated without changing
the meaning of the program except for the execution of constructors
and destructors associated with the use of the temporary object
(12.2), then the exception in the handler can be initialized directly
with the argument of the throw expression. When the thrown object is a
class object, and the copy constructor used to initialize the
temporary copy is not accessible, the program is ill-formed (even when
the temporary object could otherwise be eliminated). Similarly, if the
destructor for that object is not accessible, the program is
ill-formed (even when the temporary object could otherwise be
eliminated).
No, it's not.
15.1.5 When the thrown object is a class object, the copy/move constructor and the destructor shall be accessible,
even if the copy/move operation is elided

Why can't one ctor call another ctor to initialize the object

class Foo {
public:
Foo() { Foo(1)}
Foo(int x, int y = 0):i(x) {}
private:
int i;
}
Can anybody give me some reasonas about can I do this? If not why?
Because the language specification doesn't allow it. Just the way the language is. Very annoying if you're used to Java or other languages that allow it. However, you get used to it after a while. All languages have their quirks, this is just one of C++'s. I'm sure the writers of the specs have their reasons.
Best way around this I've found is to make a common initialization function and have both constructors call that.
Something like this:
class Foo {
public:
Foo() {initialize(1);}
Foo(int nX) { initialize(nx); }
private:
void initialize(int nx) { x=nx; }
int x;
};
It's a language design choice.
A constructor is a one time (per-object) operation that creates a new object in uninitialized memory. Only one constructor can be called for an object, once it has completed the object's lifetime begins and no other constructor can be called or resumed on that object.
At the other end of its life a destructor can only (validly) be called once per object and as soon as the destructor is entered the object's lifetime is over.
A prinicipal reason for this is to make explicit when an object destructor will be run and what state it can expect the object to be in.
If a class constructor completes successfully then it's destructor will be called, otherwise the object's lifetime has never begun and the destructor will not be called. This guarantee can be important when an object acquires resources in its constructor that need to be released in its destructor. If the resource acquisition fails then the constructor will usually be made to fail; if the destructor ran anyway it might attempt to release an resource that had never been successfully acquired.
If you allow constructors to call each other it may not be clear if a calling or a called constructor is responsible for the resource. For example, if the calling constructor fails after the called constructor returns, should the destructor run? The called constructor may have acquired something that needs releasing or perhaps that was what caused the calling construtor to fail and the destructor shouldn't be called because the resource handle was never valid.
For simplicity of the destruction rules it is simpler if each object is created by a single constructor and - if created successfully - destroyed by a single destructor.
Note that in C++11 a constructor will be able delegate to a different constructor, but there are limitations that don't really relax the principal of one construction per object. (The prinicipal constructor can forward to a target constructor, but if it does it must not name anything else (base classes or members) in its initializer list. These will be initialized by the target constructor, once the target constructor returns the body of the prinicipal constructor will complete (further initialization). It is not possible to re-construct any bases or members, although it allows you to share constructor code between constuctors.)
You cant do this. See section 10.3: http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.3. You can try to do it but doing so will construct a new temp object (not this) and be destroyed once control moves on.
What you can do however is to create a private function that initializes variables, one that your default constructor or a parameterized constructor can both call.
There is a really hideous hack I have seen used to call another ctor. It uses the placement new operation on the this pointer. erk
Like this:
Class::Class(int x) : x_(x) {}
Class::Class() {
new (this) Class(0);
}
Class::Class(const Class &other) : x_(other.x_) {}
Class& operator=(const Class &other) {
new (this) Class(other);
return *this;
}
Note that I am not recommending this, and I don't know what horrible effects it might have on C++ structures like virtual base classes, etc. But I expect that there are some.
Although as per standards vendors are free to implement data binding in their own ways, if we consider the most popular implementation: this pointer, we can see a reason why this can't be implemented.
Assume you have a class:
class A
{
public:
A(){}
A(int a){}
} ;
With the this pointer implementation, this class would look something like:
class A
{
public:
A(A *this){}
A(A *this,int a){}
} ;
Typically you would create objects like this:
A ob ;
Now when compiler sees this, it allocates memory for this and passes the address of this allocated memory block to the constructor of A which then constructs the object. It would try to do the same every time for each constructor called.
Now when you try calling a constructor within another constructor, instead of allocating new memory the compiler should pass the current objects this. Hence inconsistency!
Then another reason which i see is that even though you might want to call a constructor within another, u would still want a constructor to call default constructors for all the objects within the class. Now if one constructor were to call another, the default construction should happen for the first constructor and not for the subsequent one's. Implementing this behavior means that there would be several permutations which need to be handled. If not, then degraded performance as each constructor would default construct all the objects enclosed.
This is what i can think of as possible reasons for this behavior and do not have any standards to support.