Order of Member Constructor and Destructor Calls

Order of member constructor and destructor calls

In other words, are members guaranteed to be initialized by order of declaration and destroyed in reverse order?

Yes to both. See 12.6.2

6 Initialization shall proceed in the
following order:

  • First, and only for
    the constructor of the most derived
    class as described below, virtual base
    classes shall be initialized in the
    order they appear on a depth-first
    left-to-right traversal of the
    directed acyclic graph of base
    classes, where “left-to-right” is the
    order of appearance of the base class
    names in the derived class
    base-specifier-list.

  • Then, direct
    base classes shall be initialized in
    declaration order as they appear in
    the base-specifier-list (regardless of
    the order of the mem-initializers).

  • Then, non-static data members shall be
    initialized in the order they were
    declared in the class definition
    (again regardless of the order of the
    mem-initializers).

  • Finally, the
    compound-statement of the constructor
    body is executed. [ Note: the
    declaration order is mandated to
    ensure that base and member subobjects
    are destroyed in the reverse order of
    initialization. —end note ]

What is the order in which the destructors and the constructors are called in C++

The order is:

  1. Base constructor
  2. Derived constructor
  3. Derived destructor
  4. Base destructor

Example:

class B
{
public:
B()
{
cout<<"Construct B"<<endl;
}

virtual ~B()
{
cout<<"Destruct B"<<endl;
}
};

class D : public B
{
public:
D()
{
cout<<"Construct D"<<endl;
}

virtual ~D()
{
cout<<"Destruct D"<<endl;
}
};



int main(int argc, char **argv)
{
D d;
return 0;
}

Output of example:

Construct B

Construct D

Destruct D

Destruct B

Multiple levels of inheritance works like a stack:

If you consider pushing an item onto the stack as construction, and taking it off as destruction, then you can look at multiple levels of inheritance like a stack.

This works for any number of levels.

Example D2 derives from D derives from B.

Push B on the stack, push D on the stack, push D2 on the stack. So the construction order is B, D, D2. Then to find out destruction order start popping. D2, D, B

More complicated examples:

For more complicated examples, please see the link provided by @JaredPar

What order are destructors called and member variables destroyed in C++ using inhertitance?

constructor: first base, then derived

destruction:

  • ~derived
  • ~member derived
  • ~base
  • ~member base

code:

class member {
string s;

public:
member(string s) {
this-> s = s;
}

~member() {
cout << "~member " << s << endl;
}
};

class base {
member m;
public:
base() : m("base"){
}

~base() {
cout << "~base" << endl;
}
};

class derived : base{
member m2;
public:

derived() :m2("derived") { }

~derived() {
cout << "~derived" << endl;
}
};

int main(int argc, const char * argv[]) {
derived s;

return 0;
}

References & virtual destructor

When you plan to dynamically allocate (i.e. when you use the keywords new & delete) a derived object, then always have a virtual or a protected destructor on your base. Dynamically deleting the object on the base class reference would otherwise lead to memory leaks in the example below:

class base {
member m;
public:
base() : m("base"){
}

/* correct behaviour is when you add **virtual** in front of the signature */
~base() {
cout << "~base" << endl;
}
};

class derived : public base{
member m2;
char* longArray;
public:

derived() :m2("derived") {
longArray = new char[1000];
}


~derived() {
delete[] longArray; // never called
cout << "~derived" << endl;
}
};

int main(int argc, const char * argv[]) {
base *s = new derived; // mind the downcast to **base**

delete s; /* only the non-virtual destructor on the base and its members is called.
No destructor on derived or its members is called.
What happens to the memory allocated by derived?
**longArray** is leaked forever.
Even without **longArray**, it most probably **leaks** memory, as C++ doesn't define its behaviour
*/
return 0;
}

Output:

  • ~base
  • ~member base

Only base data is cleaned up, and longArray leaks.

Explain order of constructor/destructor calls in this C++ code

Let's go step by step with the first object being constructed:

new Class2;

This is the first object you're contructing, let's called it p.

BaseClass()

p's BaseClass.

Class1()

p's Class1, the subclass of BaseClass gets constructed.

BaseClass()

This is the id member of Class2 being constructed.

Class2()

And now, finally, Class2, p itself.

So, despite your belief otherwise, Class2() is printed after Class1(). Except that you forgot that Class2 also has an id member, that's a BaseClass, and which must also be constructed before the Class2::Class2() constructor gets invoked. You believed that you were seeing the second newed object's BaseClass being constructed, but what was really getting constructed was the BaseClass member object.

P.S. This is C++. In C++ we use std::cout instead of printf(). printf() is so ...last century.

Order of Destructor Calling When Leaving Scope? (C++)

A derived destructor is called before an ancestor destructor. So the Child destructor body will be called first, then the Parent destructor body next. And constructed objects are destructed in reverse order, so the Boy object will be destructed before the Man object is destructed.

C++ constructor & destructor order

Constructors are called upwards in the hierarchy:

- base class member objects
- base class constructor body
- derived class member objects
- derived class constructor body

The output is correct.

Let's simplify your code:

struct BaseMember
{
BaseMember() { cout << "base member" <<endl; }
};
struct Base
{
BaseMember b;
Base() { cout << "base" << endl; }
};
struct DerivedMember
{
DerivedMember() { cout << "derived member" << endl; }
};
struct Derived : public Base
{
DerivedMember d;
Derived() { cout << "derived" << endl; }
};

Derived d;

When d is created, it will first create the Base part. Before it enters the constructor body, all member objects are initialized. So BaseMember is the first object initialized.

Next, the constructor of Base is entered.

Before, the constructor of Derived enters, member objects of Derived are initialized, so DerivedMember is created, next Derived constructor is called.

This happens because when you enter the constructor body of a derived class, base classes and member objects must be completely initialized.

EDIT As Matthieu pointed out, the order in which the member objects are initialized is specified by the order in which they appear in the class definition, not the order in which they appear in the initializer list.



Related Topics



Leave a reply



Submit