Search code examples
c++language-lawyerinitializer-list

constructor initializer lists vs default initializer


In the following example below (c++11):

#include <iostream>

struct foo {
    foo() = default;
    foo(int x): v1{x} {}

    int v1 = 0;
    int v2 {v1};

    void print() const {
        std::cout<<"v1:"<<v1<<" v2:"<<v2<<std::endl;
    }
};

int main() {
    const auto bar1 = foo();
    bar1.print();  // prints v1:0 v2:0
    const auto bar2 = foo(42);
    bar2.print();  // prints v1:42 v2:42
}

I understand about the rule of v1. bar1.v1 is default initialized, and bar2.v1 is intialized by the constructor, with default initializer ignored.

What I am curious about is v2, even though bar2.v2 is default initialized, it will use the v1 that is initialized by the constructor. My question is: is this the correct behavior according to c++ standard? I cannot seem to find a good source for this.


Solution

  • Whether default initialized or initialized in the member initializer list, the member variables are initialized in the order of declaration, so yes, this is exactly how it should be.

    class.base.init/13:

    13 In a non-delegating constructor, initialization proceeds in the following order:

    • (13.1) First, and only for the constructor of the most derived class ([intro.object]), virtual base classes are 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 classes in the derived class base-specifier-list.
    • (13.2) Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
    • (13.3) Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
    • (13.4) Finally, the compound-statement of the constructor body is executed.
      [Note 6: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note]