My assumption is that the code below ill-formed NDR? But why?

Your code has undefined behavior due to [class.base.init]/9

In a non-delegating constructor, if a given potentially constructed subobject is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer), then

  • if the entity is a non-static data member that has a default member initializer ([class.mem]) and either

    [...] the constructor's class is not a union [...]

    the entity is initialized from its default member initializer as specified in [dcl.init];

So, that means

struct A{
    int i = j + 1;
    int j = 1;
};

is translated to

struct A{
    A() : i(j + 1), j(1) {}
    int i;
    int j;
};

and since i is initialized first it uses an uninitialized variable and is undefined behavior.


I think that the code is equal to following:

struct A{
    int i;
    int j;
    A():i(j + 1),j(1){}
};

Which shows that the compilers are right. Because the members are initialized in the order (stated somewhere in the standard*) in which they were declared. The in-place declaration initialization should be just syntactic sugar for their initialization in all ctors. So, the code indeed has undefined behaviour because j is an uninitialized variable.

EDIT: * Found it [10.9.2 Initializing bases and members] (http://eel.is/c++draft/class.base.init)

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.