C 11联合会的空列表初始化 - 是否保证可以初始化工会的全长
C++11 empty list Initialization of a union - is it guaranteed to initialize the full length of the union?
在C 11中,我有以下联合:
union SomeData
{
std::uint8_t Byte;
std::uint16_t Word;
std::uint32_t DWord;
unsigned char String[128];
};
如果我这样初始化了联盟;
SomeData data {};
是否可以保证联盟的整个内容将"零"输出?换一种方式;联合的空列表限制器在功能上等效将联合置于零?:
memset(&data, 0, sizeof(data));
特别是我担心字符串数据。我想确保字符串的整个长度包含零。它似乎在我当前的编译器中起作用,但是规格的语言保证这始终是真实的?
如果不是:有没有更好的方法将联合的全长初始化为零?
no,不能保证将整个联盟归零。只有第一个被宣布的联盟成员加上任何填充,保证将被归零(以下证明)。
因此,为了确保联合对象的整个内存区域为零,您有以下选项:
- 订购成员,使最大的成员首先是零。
- 使用
std::memset
或等效功能。为了防止意外忘记这一点,您当然可以给SomeData
一个默认的构造函数,该构造器称为此。
引用C 11:
8.5.4 [dcl.init.list]/3
T
类型的对象或引用的列表命令定义如下:
- 如果初始化器列表没有元素,并且
T
是具有默认构造函数的类类型,则该对象为 价值定性。
8.5 [dcl.init]/7
to value-initialize 类型
T
的对象表示:
- 如果
T
是具有用户提供的构造函数(12.1)(12.1)的(可能是CV符合条件的)类类型(第9条),则T
的默认构造函数称为(如果T
没有可访问的默认值,则将初始化不正确 构造函数);- 如果
T
是没有用户提供的构造函数的(可能是CV的)非工会类类型,则该对象 是零启动化的,如果T
隐式宣布默认构造函数是非平凡的,则该构造函数为 称为。- ...
- 否则,该对象为零。
8.5 [dcl.init]/5:
to 零initialize 类型
T
的对象或引用是:...
- 如果
T
是(可能是CV合格的)联合类型,则该对象的第一个非静态数据成员为零initialized 填充物初始化为零位;
从这些引用中,您可以看到,使用{}
来初始化data
会导致对象进行价值键化(因为SomeData
是具有默认构造函数的类类型)。
没有用户提供的默认构造函数( SomeData
为)的价值限制的联合表示零限制。
最后,零启动联合意味着零分化其第一个非静态数据成员。
整个联合将被归零。更确切地说,联盟的第一个成员将默认初始化,并且联盟中的所有剩余字节将设置为0,为 padding 。
参考(强调我的):
8.5初始化器[dcl.init]
...5 to Zero Initialize type t type t type ty类型:
...
- 如果t是(可能是CV合格的)联合类型,则该对象的第一个非静态数据成员是零初始化和填充物初始化为零位;
这意味着联盟的第一个成员(此处std::uint8_t Byte;
)将初始化为0,并且联盟中的所有其他字节将设置为0,因为它们是填充字节。
但谨慎。如Angew "填充"所述。在标准中非常明确地指定,C编译器可以解释一下,工会中的填充字节仅是跟随最大成员的字节。我真的会发现很奇怪,因为兼容性更改是专门记录的,并且先前的版本(c)首先将所有内容初始化为0,而下一个则进行了特定的初始化。但是新的实施者无法意识到这一点...
tl/dr:我真的认为标准的目的是,联盟中的所有字节都设置为OP的示例中的0,但是对于任务关键程序,我肯定会添加一个明确的0构造函数...
- 列表初始化是否将原子初始化为零
- 使用函数声明进行函数指针初始化 - 是否可能
- 值初始化是否适用于原子对象?
- 聚合的值初始化是否使用其成员的默认初始值设定项?
- C 11联合会的空列表初始化 - 是否保证可以初始化工会的全长
- 找出静态初始化是否结束
- 非本地非内联变量的初始化:是否严格在"main()"函数调用之前进行
- 空字符数组的初始化是否有效
- 变量零初始化-是否有未定义的行为
- 0-原子的初始化是否保证将值成员设置为0
- POD 类对象初始化是否需要构造函数
- 在C++中使用类似 c 的初始化或构造函数初始化是否被认为更好
- 类内成员初始化是否删除赋值运算符
- C++11;非静态数据成员初始化是否可以访问其他数据成员
- 列表初始化是否为隐式转换
- 复制列表初始化是否在概念上调用复制 ctor
- 如何测试/验证零初始化是否发生
- C++默认初始化是否保留先前的零初始化
- 使用新结构体进行聚合初始化是否有效
- 检测CRT初始化是否在注入过程中完成