在 C++11 中,我有以下 union :
union SomeData
{
std::uint8_t Byte;
std::uint16_t Word;
std::uint32_t DWord;
unsigned char String[128];
};
如果我这样初始化 union ;
SomeData data {};
是否保证 union 的全部内容将被“清零”?换一种方式;是 union 的空列表初始化器在功能上等同于将 union 内存设置为零?:
memset(&data, 0, sizeof(data));
我特别关心字符串数据。我想确保字符串的整个长度都包含零。它似乎适用于我当前的编译器,但规范的语言是否保证它始终为真?
如果不是:是否有更好的方法将 union 的全长初始化为零?
最佳答案
不,不能保证整个 union 会被清零。只有 union 的第一个声明的成员,加上任何填充,才能保证被归零(下面的证明)。
因此,为了确保 union 对象的整个内存区域都归零,您有以下选择:
- 对成员进行排序,使最大的成员排在第一位,从而将那个清零。
- 使用
std::memset
或等效功能。为了防止不小心忘记这一点,您当然可以给SomeData
一个默认的构造函数来调用它。
引用 C++11:
8.5.4 [dcl.init.list]/3
List-initialization of an object or reference of type
T
is defined as follows:
- If the initializer list has no elements and
T
is a class type with a default constructor, the object is value-initialized.
8.5 [dcl.init]/7
To value-initialize an object of type
T
means:
- if
T
is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor forT
is called (and the initialization is ill-formed ifT
has no accessible default constructor);- if
T
is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, ifT
’s implicitly-declared default constructor is non-trivial, that constructor is called.- ...
- otherwise, the object is zero-initialized.
8.5 [dcl.init]/5:
To zero-initialize an object or reference of type
T
means:...
- if
T
is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero-initialized and padding is initialized to zero bits;
从这些引用中,您可以看到使用 {}
初始化 data
将导致对象被值初始化(因为 SomeData
是具有默认构造函数的类类型)。
在没有用户提供的默认构造函数(SomeData
是)的情况下对 union 进行值初始化意味着对其进行零初始化。
最后,零初始化一个 union 意味着零初始化它的第一个非静态命名数据成员。
关于C++11 空列表 union 的初始化 - 是否保证初始化 union 的全长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42534992/