Constructor Initialization-List Evaluation Order

Constructor initialization-list evaluation order

It depends on the order of member variable declaration in the class. So a_ will be the first one, then b_ will be the second one in your example.

Evaluation order of elements in an initializer list

It seems to me that the quote is relevant (the compiler sees an initializer list):

8.5/14,16:

The initialization that occurs in the form

T x = a;

as well as in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and aggregate member initialization (8.5.1) is called copy-initialization.

.

.

The semantics of initializers are as follows[...]: If the initializer is a braced-init-list, the object is list-initialized (8.5.4).

(more details in std::initializer_list as function argument and Folds (ish) In C++11)

Moreover any {}-list should be sequenced (the standard uses a very strong wording about this fact. See also http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1030).

So it's probably a GCC bug (fixed after gcc v4.9.0).

Indeed, trying various GCC version, I get:

GCC      with --std=c++11   without (--std=c++98)
4.7.3 fg gf <-
4.8.1 fg gf <-
4.8.2 fg gf <-
4.9.0 fg gf <-
4.9.2 fg fg
5.1.0 fg fg
5.2.0 fg fg
6.1.0 fg fg

Extended initializer lists are only available with C++11 but GCC compiles the code anyway (with a warning, e.g. see gcc -Wall -Wextra vs gcc -Wall -Wextra -std=c++11).

Why must initializer list order match member declaration order?

The warning is trying to prevent situations where you might be relying on the wrong ordering of the data members. Say you think B is initialized before A, and then you do something like this:

myClass::myClass() :
B(42), A(B) {}

Here, you have undefined behaviour because you are reading from an uninitialized B.

Order of execution in constructor initialization list

According to ISO/IEC 14882:2003(E) section 12.6.2:

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.

So, follow that order, and you'll have your order. Also according to the standard, the order is prescribed as such so that objects can be uninitialized in the precisely reverse order.

Member initializer list. Order of arguments evaluation

No, this evaluation order that would potentially cause you to leak is guaranteed not to happen. The expression within each mem-initializer is a full-expression ([intro.execution] §5.3). And [intro.execution] §9 tells us

Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.

So in other words, the evaluation of each expression used to initialize a member is completed before evaluation of the expression for the next member starts.

Initializer list *argument* evaluation order

C++ Standard 12.6.2/3:

There is a sequence point (1.9) after the initialization of each base and member. The expression-list of a mem-initializer is evaluated as part of the initialization of the corresponding base or member.

The order of the initialization is the one you specified in the question. Evaluation is part of this initialization, and the initializations can't interleave (because there is a sequence point between them).

That means that the function calls in your initializer lists are not called in the desired order, but in the order in which the member declarations appear.

List evaluation order in constructor initialization

  1. sub-object destructors should always be called in reverse order compared to sub-object constructors (otherwise way too many things will fall apart)

  2. There can be multiple constructors of the object, each with it's own order of sub-objects in the list

  3. If we call sub-object constructors in the order which is specific to each object constructor, we won't be able to get one single order for sub-object destructors.

  4. Hence, the decision to have in the order of declaration, which doesn't depend on the order of sub-objects in different object constructors.

List evaluation order in constructor initialization

  1. sub-object destructors should always be called in reverse order compared to sub-object constructors (otherwise way too many things will fall apart)

  2. There can be multiple constructors of the object, each with it's own order of sub-objects in the list

  3. If we call sub-object constructors in the order which is specific to each object constructor, we won't be able to get one single order for sub-object destructors.

  4. Hence, the decision to have in the order of declaration, which doesn't depend on the order of sub-objects in different object constructors.

Is the order of variable used in constructor initialization list important?

Do we have to use variables in initialization list in the same order as we declared in class?

Order of initialization list doesn't have impact on initialization order. So it avoids misleading behavior to use real order in initialization list.

Problem comes when there is dependencies:

class A 
{
int a;
double b;
float c;
// initialization is done in that order: a, b, c
A():a(1), c(2), b(c + 1) // UB, b is in fact initialized before c
{}
};

Will the order of variables in initialization list has any impact on memory allocation of that class/variables?

Order of initialization list doesn't have impact on layout or in initialization order.

Order of member initialization list

Initialization of member variables occurs in the order that they are declared in the class.

http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-order

and:

http://en.cppreference.com/w/cpp/language/initializer_list

3) Then, non-static data members are initialized in order of
declaration in the class definition.



Related Topics



Leave a reply



Submit