No, it is not guaranteed that the entire union will be zeroed out. Only the first declared member of the union, plus any padding, is guaranteed to be zeroed (proof below).
So to ensure the entire memory region of the union object is zeroed, you have these options:
- Order the members such that the largest member is first and thus the one zeroed out.
- Use
std::memset
or equivalent functionality. To prevent accidentally forgetting that, you can of course give SomeData
a default constructor which will call this.
Quoting 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 for T
is called (and the initialization is ill-formed if T
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, if T
’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;
From these quotes, you can see that using {}
to initialise data
will cause the object to be value-initialized (since SomeData
is a class type with a default constructor).
Value-initializing a union without a user-provided default constructor (which SomeData
is) means zero-initializing it.
Finally, zero-initializing a union means zero-initializing its first non-static named data member.