class D: A
{
B obj;
C obj2;
}
What order of construction here is guaranteed?
I know that D will be constructed after A, B and C, but what I really want to know is whether A is guaranteed to be constructed before B or C, or even whether B is guaranteed to be constructed before C.
I know you can have an explicit initialiser list:
D(): A(), B(), C()
{}
but does that initialiser list determine the order of initialisation?
Also, does whether or not any of the components do or don't have a default constructor?
From the C++03 standard ISO/IEC 14882:2003(E) §12.6.2/5 [class.base.init]:
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, nonstatic 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 body of the constructor is executed.
[Note: the declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. ]
So in this case, you are guaranteed that the order of initialization will be first the base class A, then the subobject B (since it appears first in the list of class members in the class definition), then the subobject C. The order of the initializer list is irrelevant, as is whether or not any of the members do or do not have a default constructor—if a member does not have a default constructor and it is not explicitly initialized in an initializer list, then it has an unspecified value.
but does that initialiser list determinethe ORDER of initialisation?
No. Initialization-list doesn't determine the the order of initialization of member data and the base subobject(s). Members are initialized in order of their declaration, and base subobjects are constructed in the order of their mention - from left to right:
struct A : B, C {} //B is constructed before C
Also, the base subobjects are constructed before the initialization of the member data.
struct A : B, C
{
D d;
E e;
};
Order of initialization in the above struct:
B => C => d => e
subobject subobject member member
And they're destructed in the reverse order.
Perhaps this example of broken code will help illustrate:
If I define a class like so:
class Connection {
boost::asio::tcp::ip::socket _socket;
boost::asio::io_service _io_service;
Connection() : _io_service(), _socket(_io_service)
{
}
};
This will fail in all modern compilers. Because _socket is defined first as a class member, the initialization list will try to initialize it first, despite the fact that the initialization list asks the compiler to initialize _io_service first. But since _io_service has not yet been initialized (the socket constructor depends on an initialized _io_service), the initialization of _socket will cause a segfault.
Perhaps somebody can quote the appropriate section of the standard that dictates this behaviour.
For the second half of the question, base classes will always be initialized before the classes own members.
Related
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 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, nonstatic 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 body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 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, nonstatic 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 body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 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, nonstatic 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 body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 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, nonstatic 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 body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.
In the following code, when the ctor of X is called will the ctor of A or B be called first? Does the order in which they are placed in the body of the class control this? If somebody can provide a snippet of text from the C++ standard that talks about this issue, that would be perfect.
class A {};
class B {};
class X
{
A a;
B b;
};
The order is the order they appear in the class definition - this is from section 12.6.2 of the C++ Standard:
5 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, nonstatic 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 body
of the constructor is executed. [Note:
the declaration order is mandated to
ensure that base and member subobjects
are destroyed in the reverse order of
initialization. ]
Initialization is always in the order that the class members appear in your class definition, so in your example a, then b.
There is a sequence point between the initialization of each member and you can pass a reference to a yet-to-be initialized member into the constructor of a class member but you would only be able to use it in limited ways (such as taking its address to form a pointer), other uses may well cause undefined behaviour.
Destruction of class members always happens in the reverse order of construction.
Order of initialization of bases and members is defined in 12.6.2 [class.base.init]/5.