C++ destructors question - c++

With regards to the sample code below, why is the destructor for the base class called twice?
class Base {
public:
Base() {
std::cout << "Base::Base()" << std::endl;
}
~Base() {
std::cout << "Base::~Base()" << std::endl;
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived::Derived()" << std::endl;
}
~Derived() {
std::cout << "Derived::~Derived()" << std::endl;
}
};
int main() {
Base a = Derived();
return EXIT_SUCCESS;
}
Here is a sample of the output when the program is run:
Base::Base()
Derived::Derived()
Derived::~Derived()
Base::~Base()
Base::~Base()

What happens is called slicing. You initialize an object of type Base with an object of type Derived. Since any object of type Derived has also an object of type Base contained (called "base-class sub-object"), there will be two Base objects and one Derived object in existance throughout the program. The Derived object (and its base-class sub-object of type Base) only exists for the time of initialization, while the remaining Base object exists until end of main.
Since there are two Base objects and one Derived object, you will also see one more Base destructors run.

A copy constructor is being used. If you want to see what is going on, instrument the copy constructor too:
Base( const Base & ) {
std::cout << "Base::Base( const Base &)" << std::endl;
}
and similarly for Derived.
Note that this has NOTHING to do with the destructors not being virtual.

When you say Derived() in main() it creates a temporary object which is then copied into object a. Hence there are two objects because of which destructor is called twice. Also, as others pointed out your base class destructor should be virtual.

Because you create a temporary of type Derived before copy-constructing a with it. So this is basically what happens:
Derived d(); // Your temporary of type Derived is created
Base a(d); // The temporary is used to call a's copy constructor
d.Derived::~Derived(); // The temporary is destroyed, calling both ~Derived and ~Base
a.Base::~Base(); // The nonvirtual destructor on a is called, so ~Base is called, but not ~Derived
So apart from the unnecessary copying at the beginning (which the compiler may optimize away), the actual error is that ~Base isn't virtual.
Edit
Oops, completely missed the slicing that takes place as litb pointed out. Read his answer instead :)

Adding in the following will make the program more clear:
Base(const Base& base){
std::cout << "Base::Base(const Base& base)" << std::endl;
}
The compiler will automatically create a copy constructor for you. By defining it yourself, (and by adding in the print) you can see that the number of constructors and destructors match
Base::Base()
Derived::Derived()
Base::Base(const Base& base)
Derived::~Derived()
Base::~Base()
Base::~Base()

You need a virtual destructor.

You have one stack variable and one temporary - total of two objects constructed - so it's logical for the destructor to be called twice.

1) A temporary object of Derived type is built (Derived::Derived() and Base::Base() are called)
2) The temp object is copied into "a"
3) The temporary object is destroyed ( Derived::~Derived() and Base::~Base() are called)
4) return EXIT_SUCCESS;
5) "a" is destroyed, so Base::~Base() is called

Related

Confusion regarding exceptions in C++ constructors

I've found what looks like contradictory answers regarding exceptions being thrown inside constructors in C++. One of the answers in this link says that if an exception is thrown inside a constructor, it is assumed that construction is not complete, and therefore the the destructor is not called. But this link discusses the RAII concept, using the example of a mutex created in a constructor and cleaned up in a destructor. It says that if a mutex is created in the constructor and then the constructor calls a function that throws an excpetion and no exception handler is defined, then the destructor will still be called and the mutex will be cleaned up. What
am I missing?
The destructor of the object being constructed is not executed, but all its members that were constructed are destructed; for example:
struct A {
A(int x) { ... }
~A() { ... }
};
struct B {
A a1, a2, a3;
B() : a1(1), a2(2), a3(3) { ... }
~B() { ... }
};
if when building a B instance the construction of a1 goes well, then the construction of a2 goes well but the construction of a3 throws an exception then what happens is that a2 will be destroyed (calling ~A), then a1 will be destroyed but ~B will NOT be called because the constructor didn't complete (the body didn't even start).
Even if the exception is thrown inside the ... body of B() then all of the A subobjects will be destroyed by calling ~A but still ~B will not be called.
Only if the constructor of B is completed what you get is a real B instance and then, when destroyed, ~B will be called to execute destruction code.
Let's look at this piece of code:
#include <iostream>
#include <stdexcept>
class A {
public:
A() {
std::cout << "A's constructor\n";
}
~A() {
std::cout << "A's destructor\n";
}
};
class B {
public:
B() {
std::cout << "B's constructor - begin\n";
throw std::runtime_error("Error");
std::cout << "B's constructor - end\n";
}
~B() {
std::cout << "B's destructor\n";
}
private:
A a;
};
int main() {
try {
B b;
} catch(const std::runtime_error& exc) {
std::cerr << exc.what() << '\n';
}
}
Here's the program's output:
A's constructor
B's constructor - begin
A's destructor
Error
In general, when an object is constructed first its fileds's constructors are invoked and then the constructor for the object is executed. For every successfully executed constructor there must be a destructor called. The destructors are called in reverse order. If a constructor fails then there's no destructor called but if during construction of an object some or all of its fields are constructed then they will be destroyed.
Coming back to the example, in the main function I create an object of class B. The object contains a member of class A. When the b object is created, first it's fields (in this case it's the member called a) are constructed - this is the first line of the output. Then the constructor of the b object begins execution (second line of output). The B's constructor throws an exception. Since the contructor of b's field (that is constructor of a) has already been successfully executed, a's destructor must be called - thrid line of output. Now, the b's constructor has not successfully finished its execution so the destructor is not going to be called for b. The last line of output is the effect of exception handling code in the main function.
In this example you can see that when a constructor succeeds then some time later a corresponding destructor is called. However if a constructor fails no destructor for the object will be called.
Successfully executed constructors and destructors are always paired. It's a very general rule and it's valid also for base classes (if any), objects allocated in arrays, objects allocated on stack etc. - even very weird and complicated cases are always handled this way.

Accessing owner in destructor c++

Say there is an object A which owns an object B via std::unique_ptr<B>. Further B holds a raw pointer(weak) reference to A. Then the destructor of A will invoke the destructor of B, since it owns it.
What will be a safe way to access A in the destructor of B? (since we may also be in the destructor of A).
A safe way me be to explicitly reset the strong reference to B in the destructor of A, so that B is destroyed in a predictable manner, but what's the general best practice?
I'm no language lawyer but I think it is OK. You are treading on dangerous ground and perhaps should rethink your design but if you are careful I think you can just rely on the fact that members are destructed in the reverse order they were declared.
So this is OK
#include <iostream>
struct Noisy {
int i;
~Noisy() { std::cout << "Noisy " << i << " dies!" << "\n"; }
};
struct A;
struct B {
A* parent;
~B();
B(A& a) : parent(&a) {}
};
struct A {
Noisy n1 = {1};
B b;
Noisy n2 = {2};
A() : b(*this) {}
};
B::~B() { std::cout << "B dies. parent->n1.i=" << parent->n1.i << "\n"; }
int main() {
A a;
}
Live demo.
since the members of A are destructed in order n2 then b then n1. But this is not OK
#include <iostream>
struct Noisy {
int i;
~Noisy() { std::cout << "Noisy " << i << " dies!" << "\n"; }
};
struct A;
struct B {
A* parent;
~B();
B(A& a) : parent(&a) {}
};
struct A {
Noisy n1 = {1};
B b;
Noisy n2 = {2};
A() : b(*this) {}
};
B::~B() { std::cout << "B dies. parent->n2.i=" << parent->n2.i << "\n"; }
int main() {
A a;
}
Live demo.
since n2 has already been destroyed by the time B tries to use it.
What will be a safe way to access A in the destructor of B? (since we may also be in the destructor of A).
There isn't safe way:
3.8/1
[...]The lifetime of an object of type T ends when:
— if T is a class type with a non-trivial destructor (12.4), the destructor call starts [...]
I think it's straightforward that you can't access object after it's lifetime has ended.
EDIT: As Chris Drew wrote in comment you can use object after it's destructor started, sorry, my mistake I missed out one important sentence in the standard:
3.8/5
Before the lifetime of an object has started but after the storage which the object will occupy has been
allocated or, after the lifetime of an object has ended and before the storage which the object occupied is
reused or released, any pointer that refers to the storage location where the object will be or was located
may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise,
such a pointer refers to allocated storage (3.7.4.2), and using the pointer as if the pointer were of type void*,
is well-defined. Such a pointer may be dereferenced but the resulting lvalue may only be used in limited
ways, as described below. The program has undefined behavior if:
[...]
In 12.7 there is list of things you can do during construction and destruction, some of the most important:
12.7/3:
To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference)
to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or
indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. To form a pointer to (or
access the value of) a direct non-static member of an object obj, the construction of obj shall have started
and its destruction shall not have completed, otherwise the computation of the pointer value (or accessing
the member value) results in undefined behavior.
12.7/4
Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2).
When a virtual function is called directly or indirectly from a constructor or from a destructor, including
during the construction or destruction of the class’s non-static data members, and the object to which the
call applies is the object (call it x) under construction or destruction, the function called is the final overrider
in the constructor’s or destructor’s class and not one overriding it in a more-derived class. If the virtual
function call uses an explicit class member access (5.2.5) and the object expression refers to the complete
object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the
behavior is undefined.
As has already been mentioned there is no "safe way". In fact as has been pointed out by PcAF the lifetime of A has already ended by the time you reach B's destructor.
I also just want to point out that this is actually a good thing! There has to be a strict order in which objects get destroyed.
Now what you should do is tell B beforehand that A is about to get destructed.
It is as simple as
void ~A( void ) {
b->detach_from_me_i_am_about_to_get_destructed( this );
}
Passing the this pointer might be necessary or not depending on the design ob B (If B holds many references, it might need to know which one to detach. If it only holds one, the this pointer is superfluous).
Just make sure that appropriate member functions are private, so that the interface only can be used in the intended way.
Remark:
This is a simple light-weight solution that is fine if you yourself completely control the communication between A and B. Do not under any circumstances design this to be a network protocol! That will require a lot more safety fences.
Consider this:
struct b
{
b()
{
cout << "b()" << endl;
}
~b()
{
cout << "~b()" << endl;
}
};
struct a
{
b ob;
a()
{
cout << "a()" << endl;
}
~a()
{
cout << "~a()" << endl;
}
};
int main()
{
a oa;
}
//Output:
b()
a()
~a()
~b()
"Then the destructor of A will invoke the destructor of B, since it owns it." This is not the correct way of invocation of destructors in case of composite objects. If you see above example then, first a gets destroyed and then b gets destroyed. a's destructor won't invoke b's destructor so that the control would return back to a's destructor.
"What will be a safe way to access A in the destructor of B?". As per above example a is already destroyed therefore a cannot be accessed in b's destructor.
"since we may also be in the destructor of A).". This is not correct. Again, when the control goes out of a's destructor then only control enters b's destructor.
Destructor is a member-function of a class T. Once the control goes out of destructor, the class T cannot be accessed. All the data-members of class T can be accessed in class T's constructors and destructor as per above example.
If you look only on the relations of the two classes A and B, the construction is well:
class A {
B son;
A(): B(this) {}
};
class B {
A* parent;
B(A* myparent): parent(myparent) {}
~B() {
// do not use parent->... because parent's lifetime may be over
parent = NULL; // always safe
}
}
The problems arise, if objects of A and B are proliferated to other program units. Then you should use the tools from std::memory like std::shared_ptr or std:weak_ptr.

Validity of "this" in destructor

On the last line of a destructor, I have a diagnostic type message which takes a printf-like form:
"object destroyed at %p", this
I have concerns though about how well this is defined at such a point.
Should I have such reservations? Is the behaviour well-defined?
According to the C++ Standard (12.4 Destructors)
8 After executing the body of the destructor and destroying any
automatic objects allocated within the body, a destructor for class
X calls the destructors for X’s direct non-variant non-static data
members, the destructors for X’s direct base classes and, if X is the
type of the most derived class (12.6.2), its destructor calls the
destructors for X’s virtual base classes.
So your code is well-formed. All destructors of non-static data members and base classes are called after executing the body of the destructor.
Well, the pointer itself certainly still exists (it's just an address, after all). There should be no problem to print the pointer value.
On the other hand, everything that you did in the destructor has already happened. Attributes may already have been delete'd, etc, so you have to avoid anything that accesses those.
This has perfectly well defined behaviour. Consider that the this pointer can be used implicitly or explicitly throughout the destructor, e.g. whenever you access a member variable for things like delete ptr_;. After the destructor returns, the members are destroyed in reverse order of declaration/creation then the base destructors invoked.
As you might now, you can access your class members from the destructor. This would not be working if the this pointer was invalid. So you can safely assume that the address this points to is still the same that you might have printed in the constructor.
Inside the destructor the this pointer is well defined, as are all the members and bases (that will be destroyed in construction reverse order after the destructor return). So printing the address it refers is not UB.
The only thing is that the object itself cannot be assumed anymore as "polymorphic", since the derived components had already been destroyed.
class A
{
public:
virtual void fn() { std::cout << "A::fn" << std::endl; }
virtual ~A() { fn(); } //< will call A::fn(), even if B is destroying
};
class B: public A
{
public:
virtual void fn() { std::cout << "B::fn" << std::endl; }
virtual ~B() {}
};
int main()
{
B b;
A& a = b;
a.fn(); //< will print B::fn(), being A::fn virtual and being B the runtime-type of the a's referred object
return 0; //< will print A::fn() from b's A's component destructor
}

Copy-constructor of multiply-inherited classes

Consider this piece of code:
#include <vector>
#include <iostream>
using namespace std;
class Base
{
char _type;
public:
Base(char type):
_type(type)
{}
~Base() {
cout << "Base destructor: " << _type << endl;
}
};
class uncopyable
{
protected:
uncopyable() {}
~uncopyable() {}
private:
uncopyable( const uncopyable& );
const uncopyable& operator=( const uncopyable& );
};
class Child : public Base, private uncopyable
{
int j;
public:
Child():
Base('c')
{}
~Child() {
cout << "Child destructor" << endl;
}
};
int main()
{
vector<Base> v;
Base b('b');
Child c;
v.push_back(b);
v.push_back(c);
return 0;
}
The output on my system is:
Base destructor: b
Child destructor
Base destructor: c
Base destructor: b
Base destructor: b
Base destructor: c
My questions are:
Why is the destructor of Base (with type b) called three times instead of two (do we have more than two copies of object b)?
What happens when we copy an object of type Child, considering the copy-constructor of one of its parents is private. Is it undefined behavior?
I was expecting to get a compile-time error whenever I try to copy an object of type Child. I thought the child's default copy-constructor would try to call the private copy-constructor of the Uncopyable class and cause compilation error. Why doesn't it give compile errors?
The reason the code is designed this way is because the Child class is huge.
The desired behavior is throwing away the child data whenever a client tries to copy a Child object (calling the destructor of Child without calling the destructor of Base).
This piece of code achieves that, but I guess it results in undefined behavior and has memory leak (never calls the destructor of Child for the copied instance).
Here is what happens in your code:
int main()
{
vector<Base> v; // 1
Base b('b'); // 2
Child c; // 3
v.push_back(b); // 4
v.push_back(c); // 5
return 0;
} // 6
line 1: vector v constructed
line 2: Base b constructed (calling Base's constructor)
line 3: Child c constructed (calling Child's constructor and Base's constructor)
line 4: v is current at maximum capacity and needs to be resized.
Memory is allocated for 1 element of Base by v.
Base b copied into v[0] (calling Base's copy constructor).
line 5: v is again at maximum capacity and needs to be resized.
Memory is allocated for 2 elements of Base by v.
The old v[0] is copied into the new v[0] (calling Base's copy constructor).
The old v[0] is deleted (calling Base's destructor ("Base destructor: b")).
Child c is copied into v[1] (calling Base's copy constructor).
line 6: c, b, and v run out of scope.
Child c is deleted (calling Child's destructor ("Child destructor") then Base's destructor ("Base destructor: c").
Base b is deleted (calling Base's destructor ("Base destructor: b")).
Base v[0], v[1] are deleted (calling Base's destructor twice ("Base destructor: b", "Base destructor: c")).
There is no memory leak - for every constructor in the above sequence a corresponding destructor is called.
Additionally, you seem to be very confused about copy constructors. Child c gets passed to push_back as a Base& - which then calls Base's copy constructor as expected. Since Base's implicit copy constructor is not virtual or overriden, having Child derive from uncopyable does nothing to change this.
Note that a vector<Base> cannot ever store an object of type Child; it only knows to allocate enough memory for a Base. What occurs when assigning an instance of Child to a Base is known as slicing, which, while often unintended and misunderstood, seems like it may actually be what you want in your described scenario.
I was expecting to get a compile-time error whenever I try to copy an object of type Child.
You aren't copying a Child object. When you put Child c into a vector<Base>, only the Base gets copied. It's basically the same as executing b = c;. If you do copy/assign Child you will get an error.
Child d = c; // compile error
The default copy constructor will call the copy constructors of any base class and member objects and do a bitwise copy for primitives and pointers.
EDIT: The answer is wrong.. currently editing to a better response.
Why is the destructor of Base (with type b) called three times instead of two (do we have more than two copies of object b)?
Most likely is that the Vector is making a copy of b. Vectors do that often.
What happens when we copy an object of type Child, considering the copy-constructor of one of its parents is private. Is it undefined behavior?
No. The copy constructor of C will call the copy constructor of the base classes. So if base class copy constructors are private, it will not compile.
I need to get a compile-time error whenever I try to copy an object of type Child while, permitting copying of Base class objects. What is the best way to do that?
Declare a private copy-constructor for Child like so:
private:
Child(const Child& a) {
throw "cannot make a copy";
}
The desired behavior is throwing away the child data whenever a client tries to copy a Child object (calling the destructor of Child without calling the destructor of Base).
Not sure what you mean. The copy constructor means creating a new object. You cannot do operations on the (old) object.

What happens if an exception is raised in constructor [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What happens to base class destructor if a derived class destructor throws an exception
If I throw an exception in the constructor of a derived class, is the destructor called to clean up the base class?
The destructors of the base class(es) are then called in the reverse order.
Before that, the destructors of any already initialized member will also get called.
However, the destructor of the currently constructed derived-class won't get called, as this part of the object will not have been really constructed yet.
Yes. For example, consider:
#include <iostream>
class B
{
public:
B() { std::cout << "B()\n"; }
~B() { std::cout << "~B()\n"; }
};
class D : public B
{
public:
D() { std::cout << "D()\n"; throw 23; }
~D() { std::cout << "~D()\n"; }
};
int main()
try
{
D d;
return 0;
}
catch(...) {}
Output:
B()
D()
~B()
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.10
Every data member inside your object should clean up its own mess.
If a constructor throws an exception, the object's destructor is not
run. If your object has already done something that needs to be
undone (such as allocating some memory, opening a file, or locking
a semaphore), this "stuff that needs to be undone" must be
remembered by a data member inside the object.
Base destructors are guaranteed to be called, but not the destructor of the object itself.
Yes. Once construction of a base or member sub-object is complete, that sub-object will be properly destroyed if an exception is thrown.
Actually, throwing an exception in the constructor is one of the COMMON ways to detect object construction failure as long as it's properly handled by the caller, as there is NO return value of constructor.