Search code examples
c++initializationlanguage-lawyer

Order of initialization with mixed inline and constructor initializations


[This question arised from this question]

Consider the following program:

#include <iostream>

struct Foo
{
    const size_t size;
    int* arr{ create_arr(size) };

    Foo(size_t s)
        : size{ set_size(s) }
    {
    }

    static int* create_arr(size_t s)
    {
        std::cout << "Creating array with size " << s << '\n';
        return new int[s];
    }

    static size_t set_size(size_t s)
    {
        std::cout << "Setting size to " << s << '\n';
        return s;
    }
};

int main()
{
    Foo f(10);
}

The inline initialization of arr depends on the value of size. But the value of size is only initialized in the constructor initializer list.

Both GCC and Clang handles it correctly, and will complain if the declaration order of size and arr is mirrored. I've also heard that MSVC will do the "right" thing (according to comments in the other question).

My question is: Is this well-defined?

I know that initialization is done in declaration order, but does it include inline initialization as well?


Solution

  • I know that initialization is done in declaration order, but does it include inline initialization as well?

    Yes, it must, see class.base.init :

    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 (4.5), 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: The declaration order is mandated to ensure that base and member sub

    Although the standard is not too specific here, that should be fully sufficient since default member initializers are initializers. The order in the class definition is the fundament here always. Having an exception here would be extremely contraditory to a lot of other parts of the standard in terms of initialization.

    With an additional note also within this section, the standard emphasizes that via the focus on destruction:

    [ Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. — end note ]

    So there's simply no further room for interpretations here.