我的假设是以下格式错误的NDR?但为什么?

Wal*_*ldB 7 c++ language-lawyer

[class.mem] / 6

一个类的完整类上下文是
(6.1)函数体,
(6.2)默认参数,
(6.3)noexcept-specifier([except.spec]),
(6.4)合同条件或
(6.5)默认成员初始化器

在类的成员规范内。[?注意:如果嵌套类是在封闭类的成员规范内定义的,则嵌套类的完整类上下文也是任何封闭类的完整类上下文。-?尾注?]

上面突出显示的文本似乎为以下代码段提供了支持:

#include<iostream>
struct A{
    int i = j + 1;
    int j = 1;
};

int main(){
    A a;
    std::cout << a.i << '\n';
    std::cout << a.j << '\n';
}
Run Code Online (Sandbox Code Playgroud)

,并且我希望它能打印出来

2
1
Run Code Online (Sandbox Code Playgroud)

无论GCC和铛打印

1
1
Run Code Online (Sandbox Code Playgroud)

但另外clang发出以下警告:

prog.cc:3:13: warning: field 'j' is uninitialized when used here [-Wuninitialized]
    int i = j + 1;
            ^
prog.cc:8:7: note: in implicit default constructor for 'A' first required here
    A a;
      ^
prog.cc:2:8: note: during field initialization in the implicit default constructor
struct A{
       ^
1 warning generated.
Run Code Online (Sandbox Code Playgroud)

我的假设是该代码是格式错误的NDR。但为什么?

Nat*_*ica 8

由于[class.base.init] / 9,您的代码具有未定义的行为

在非委托构造函数中,如果给定的可能构造的子对象未由mem-initializer-id指定(包括由于构造函数没有ctor-initializer而没有mem-initializer-list的情况),

  • 如果实体是具有默认成员初始化程序([class.mem])的非静态数据成员,并且

    [...]构造函数的类不是联合[...]

    从[dcl.init]中指定的默认成员初始化程序初始化该实体;

因此,这意味着

struct A{
    int i = j + 1;
    int j = 1;
};
Run Code Online (Sandbox Code Playgroud)

被翻译成

struct A{
    A() : i(j + 1), j(1) {}
    int i;
    int j;
};
Run Code Online (Sandbox Code Playgroud)

由于i首先被初始化,因此它使用了未初始化的变量,并且是未定义的行为。