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:
- Base constructor
- Derived constructor
- Derived destructor
- 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 new
ed 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
Demote Boost::Function to a Plain Function Pointer
Resolution of Std::Chrono::High_Resolution_Clock Doesn't Correspond to Measurements
High Resolution Timer With C++ and Linux
Which C I/O Library Should Be Used in C++ Code
Dividing Two Integers to Produce a Float Result
Trailing Return Type Using Decltype With a Variadic Template Function
Linux: Executing Child Process With Piped Stdin/Stdout
Std::Thread Pass by Reference Calls Copy Constructor
Nice Way to Append a Vector to Itself
Metaprograming: Failure of Function Definition Defines a Separate Function
C++ Preprocessor #Define-Ing a Keyword. Is It Standards Conforming
Prevent Static Initialization Order "Fiasco", C++
Should the Exception Thrown by Boost::Asio::Io_Service::Run() Be Caught
Heterogeneous Containers in C++
How to Know the Exact Line of Code Where an Exception Has Been Caused
Stringstream, String, and Char* Conversion Confusion
Dual Emission of Constructor Symbols
Passing a String Literal as a Type Argument to a Class Template