Wal*_*ldB 7 c++ language-lawyer
一个类的完整类上下文是
(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。但为什么?
由于[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首先被初始化,因此它使用了未初始化的变量,并且是未定义的行为。