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 开发者_StackOverflow中文版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.
精彩评论