In the following code snippet d1's initializer is passed d2 which has not been constructed yet (correct?), so is the d.j in D's copy constructor an uninitialized memory access?
struct D
{
int j;
D(const D& d) { j = d.j; }
D(int i) { j = i; }
};
struct A
{
D d1, d2;
A() : d2(2), d1(d2) {}
};
Which section开发者_StackOverflow中文版 of C++ standard discusses order of initialization of data members?
I don't have the standard handy right now so I can't quote the section, but structure or class member initialisation always happens in declared order. The order in which members are mentioned in the constructor initialiser list is not relevant.
Gcc has a warning -Wreorder
that warns when the order is different:
-Wreorder (C++ only) Warn when the order of member initializers given in the code does not match the order in which they must be executed. For instance: struct A { int i; int j; A(): j (0), i (1) { } }; The compiler will rearrange the member initializers for i and j to match the declaration order of the members, emitting a warning to that effect. This warning is enabled by -Wall.
The C++ standard (ISO/IEC 14882:2003 12.6.2/5, Initializing bases and members) says:
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.
Bullet point 3 guarantees the order of nonstatic data member initialization.
In your example it will fail:
struct A
{
D d1, d2;
A() : d2(2), d1(d2) {}
};
d1: is initialised first as it is declared first.
d2: is then initialized.
As a result the initializer list will construct d1 using a reference to an invalid object (d2).
This is one reason to turn up your compilers warning level as high as possable.
And additionaly force it to report all warnings as errors.
This phenomenon is explained/highlighted in Item 13 of Meyer's Effective C++. It says that the destructor must destroy elements in the inverse order of its constructors, therefore all constructors must initialize elements in the same order, therefore they initialize them in the order in which they're declared (instead of the sequence of the initialization lists).
Yes. A good compiler should warn you that A::d2
will be initialized after A::d1
.
精彩评论