在C 11中,我有以下联盟:
union SomeData { std::uint8_t Byte; std::uint16_t Word; std::uint32_t DWord; unsigned char String[128]; };
如果我初始化联盟,
SomeData data {};
是否保证工会的全部内容将“零”出来?换个方法是一个空的列表初始化程序,一个工会功能上等同于将工会装入零的工作:
memset(&data,sizeof(data));
特别是我关心字符串数据.我想确保字符串的整个长度都包含零.它似乎在我目前的编译器中工作,但规范的语言是否保证这一直是真的?
如果没有,是否有更好的方法将工会的全部初始化为零?
解决方法
不,不能保证整个联盟将被清除.只有第一个声明的工会成员,加上任何填充,保证被归零(下面的证明).
所以为了确保联合对象的整个内存区域被归零,你有以下选项:
>订购成员,使最大的成员是第一个,因此一个被清除.
>使用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;
从这些引号可以看出,使用{}初始化数据将导致对象进行值初始化(因为SomeData是一个默认构造函数的类类型).
值初始化没有用户提供的默认构造函数(SomeData是)的联合体意味着零初始化它.
最后,零初始化联合是指零初始化其第一个非静态命名数据成员.