我的假设是下面的代码不正确的NDR?但为什么
My assumption is that the code below ill-formed NDR? But why?
[class.mem]/6:
班级的完整上下文是
(6.1)功能主体,
(6.2) 默认参数,
(6.3)noexcept特征器([[excep.spec]),
(6.4) 合同条件,
(6.5)默认成员ritializer在 班级成员规范。[注意:一个完整的上下文 嵌套类也是任何封闭的完整上下文 类,如果嵌套类是在成员规格中定义的 封闭班级。 - 终注]
上面突出显示的文本似乎为以下片段提供了支持:
#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';
}
,我期望它可以打印
2
1
GCC和Clang Print
1
1
但此外,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.
我的假设是代码是不形成型的NDR。但是为什么?
您的代码由于[class.base.init]/9
而具有未定义的行为在非级别的构造函数中,如果给定潜在构造的子对象不是由mem-initializer-id指定的(包括没有mem-initialial-list列表的情况,因为构造函数没有ctor-initialializer),则
如果该实体是具有默认成员初始化器([class.mem])的非静态数据成员,则
[...]构造函数的类不是联合[...]
该实体是根据[dcl.init]中指定的默认成员初始化器初始化的。
所以,这意味着
struct A{
int i = j + 1;
int j = 1;
};
被翻译成
struct A{
A() : i(j + 1), j(1) {}
int i;
int j;
};
,并且由于i
首先是初始化的,因此它使用了一个非初始化的变量,并且是未定义的行为。
我认为代码等于以下:
struct A{
int i;
int j;
A():i(j + 1),j(1){}
};
这表明编译器是正确的。因为成员按顺序(标准*中的某个地方说明)初始化。原始声明初始化应该只是所有CTOR中初始化的句法糖。因此,该代码确实具有不确定的行为,因为j
是一个非初始化的变量。
编辑: *找到了[10.9.2初始化基础和成员](http://eel.is/c draft/class.base.init)
在非规定的构造函数中,初始化按以下顺序进行:
(13.1) 首先,仅对于最派生的类的构造函数([Into.Object]),虚拟基类是按照它们出现在深度优先的左右横向遍历的顺序的初始初始化的。其中"从左到右"是派生的类基准列表中基类的外观顺序。
(13.2) 然后,直接基类以声明顺序初始化,因为它们出现在基本列表中(无论mem-initializers的顺序如何)。
(13.3) 然后,非静态数据成员以在类定义中声明的顺序初始化(再次不论MEM-INITIALIZERS的顺序)。
(13.4) 最后,执行构造函数的复合态。
这里的问题是在声明和初始化j。
之前使用int i = j + 1
您应该做的是
struct A{
int j = 1;
int i = j + 1;
};
因此,应在i之前初始化j。希望这会有所帮助:)
在您给出的变量j的示例中没有初始化(gcc也许是默认的这些this thise nor Initialized积分变量为0)这就是为什么i的初始值是1,因此打印了值顺便说一句,以这种方式初始化变量不是一个好主意。而是使用构造函数请参阅此
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 为什么在全局范围内使用"extern int a"似乎不行?
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 为什么会发生堆损坏
- 为什么使用 "this" 指针调用派生成员函数?
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 为什么比较运算符如此快速
- 为什么 Serial.println(<char[]>);返回随机字符?
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 为什么不;名字在地图上是按顺序排列的吗
- 我的字符计数代码计算错误.为什么
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 为什么野牛仍在使用"int yylex(void)",却找不到"int yylex(YYS
- 为什么 std::unique 不调用 std::sort?
- 既然存在危险,为什么项目要使用-I include开关
- 我的假设是下面的代码不正确的NDR?但为什么