Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the order of initialization guaranteed by the standard?

Tags:

c++

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 of C++ standard discusses order of initialization of data members?

like image 649
Murali VP Avatar asked Nov 21 '09 01:11

Murali VP


4 Answers

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.

like image 73
James McNellis Avatar answered Nov 15 '22 21:11

James McNellis


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.
like image 28
Greg Hewgill Avatar answered Nov 15 '22 21:11

Greg Hewgill


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.

like image 43
Martin York Avatar answered Nov 15 '22 20:11

Martin York


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).

like image 20
ChrisW Avatar answered Nov 15 '22 19:11

ChrisW