[英]Aggregate Initialization Safety in C++
假设我有以下结构:
struct sampleData
{
int x;
int y;
};
并且在使用时,我想将sampleData
类型的变量初始化为已知的 state。
sampleData sample = { 1, 2 }
后来,我决定需要将其他数据存储在我的sampleData
结构中,如下所示:
struct sampleData
{
int x;
int y;
int z;
};
据我了解,从我的 pre- z
数据结构中遗留下来的两个字段初始化仍然是一个有效的语句,并且将被编译,用默认值填充缺失的字段。
这种理解正确吗? 我最近一直在 Ada 工作,它也允许聚合初始化,但会将类似的问题标记为编译错误。 假设我对上面 C++ 代码的假设是正确的,是否有一种语言结构可以将缺少的初始化值识别为错误?
只有Aggregate Classes支持以这种方式初始化变量。
如果您添加构造函数,那么问题就会消失,但是您需要稍微更改语法,并且您将失去将struct
存储在union
中的能力(除其他外)。
struct sampleData
{
sampleData(int x, int y) : x(x), y(y) {}
int x;
int y;
};
sampleData sample( 1, 2 );
添加z
(并更改构造函数)会将sample( 1, 2 )
标记为编译错误。
是的,您离开初始化列表的任何元素都将被初始化为零(对于 POD 标量类型)或使用它们的默认构造函数(对于类)。
此处引用了 C 标准中的相关语言:
[6.7.8.21] 如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小数组的字符串文字中的字符少于数组中的元素,则聚合的其余部分应隐式初始化,与具有 static 存储持续时间的对象相同。
我确信有人比我在 C++ 规范之一中找到相应的语言更有动力......
请注意,这意味着 POD 标量元素的初始化就像您写了“= 0”一样。 这意味着它将正确初始化指向 NULL 的指针并浮动到 0.0,即使它们的表示不是全零字节。 这也意味着它是递归工作的; 如果您的结构包含一个结构,则内部结构也将被正确初始化。
作为 Nemo 对 C 标准的回答的后续,这里是 C++03 标准所说的:
§8.5.1/7:
如果列表中的初始化器少于聚合中的成员,则每个未显式初始化的成员都应进行值初始化。
§8.5/5:
对
T
类型的 object 进行值初始化意味着:
- 如果
T
是具有用户声明的构造函数的 class 类型,则调用T
的默认构造函数(如果T
没有可访问的默认构造函数,则初始化格式错误);- 如果
T
是没有用户声明的构造函数的非联合 class 类型,则T
的每个非静态数据成员和基类组件都是值初始化的;- 如果
T
是一个数组类型,那么每个元素都是值初始化的;- 否则,object 被零初始化
对
T
类型的 object 进行零初始化意味着:
- 如果
T
是标量类型,则将 object 设置为转换为T
的值0
(零);- 如果
T
是非联合 class 类型,则每个非静态数据成员和每个基类子对象都初始化为零;- 如果
T
是联合类型,则对象的第一个命名数据成员)初始化为零;- 如果
T
是数组类型,则每个元素都初始化为零;- 如果
T
是引用类型,则不执行初始化。
为什么不使用
sampleData sample = { x: 1, y:2 } ;
?
但是您仍然会遇到z
被初始化为不可预测值的问题,因此最好定义一个将所有变量设置为明确定义的值的构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.