在 C++11 中,我有以下联合:
union SomeData
{
std::uint8_t Byte;
std::uint16_t Word;
std::uint32_t DWord;
unsigned char String[128];
};
如果我这样初始化联合;
SomeData data {};
是否保证entire联盟的内容将被“清零”?换一种方式;是联合的空列表初始值设定项功能等同到 memset-并集到零?:
memset(&data, 0, sizeof(data));
我特别关心字符串数据。我想确保字符串的整个长度都包含零。它似乎可以在我当前的编译器中工作,但确实如此规范的语言保证这永远是真的吗?
如果没有:是否有更好的方法将联合的全长初始化为零?
不,不保证整个联盟都会被清零。只有联合体中第一个声明的成员加上任何填充,才保证被清零(证明如下)。
因此,为了确保联合对象的整个内存区域被清零,您有以下选择:
- 对成员进行排序,使最大的成员排在第一位,从而将其清零。
- Use
std::memset
或同等功能。为了防止意外忘记这一点,你当然可以给SomeData
将调用此的默认构造函数。
引用C++11:
8.5.4 [dcl.init.list]/3
对象或类型引用的列表初始化T
定义如下:
- 如果初始值设定项列表没有元素并且
T
是具有默认构造函数的类类型,该对象是
值初始化。
8.5 [dcl.init]/7
To 值初始化类型的对象T
means:
- if
T
是一个(可能是 cv 限定的)类类型(第 9 条),具有用户提供的构造函数 (12.1),那么
默认构造函数T
被调用(并且初始化是错误的,如果T
没有可访问的默认值
构造函数);
- if
T
是一个(可能是 cv 限定的)非联合类类型,没有用户提供的构造函数,则该对象
是零初始化的,如果T
的隐式声明的默认构造函数是不平凡的,该构造函数是
叫。
- ...
- 否则,该对象将被零初始化。
8.5 [dcl.init]/5:
To 零初始化类型的对象或引用T
means:
...
- if
T
是一个(可能是 cv 限定的)联合类型,该对象的第一个非静态命名数据成员是零初始化的
并且填充被初始化为零位;
从这些引用中,您可以看到使用{}
初始化data
将导致对象被值初始化(因为SomeData
是具有默认构造函数的类类型)。
在没有用户提供的默认构造函数的情况下对联合进行值初始化(其中SomeData
is) 意味着将其初始化为零。
最后,对联合进行零初始化意味着对其第一个非静态命名数据成员进行零初始化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)