Why is a member not getting zero-initialized in this example?
I'd also go with compiler bug.
- I think we can all agree that
b
gets value-initialized (8.5.4) Using
value-initialize an object of type T means:
— 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.So what should happen is first zero-initialization, then default ctors may be called
- And with the definition:
To zero-initialize an object or reference of type T means:
— if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
Hence the following should happen:
- Fill
sizeof(B)
with zeroes - Call constructor of subobject
A
which does nothing.
I assume this is a bug in the optimization. Compare the output of -O0
to -O1
: https://godbolt.org/z/20QBoR. Without optimization the behaviour is correct. Clang on the other hand is correct in both: https://godbolt.org/z/7uhlIi
This "bug" is still present with newer standard flags in GCC: https://godbolt.org/z/ivkE5K
However I assume in C++20 B
is an "aggregate" so the behavior becomes standard.
For any class, if there is a single user-defined constructor it must be used, and A(){}
does not initialise i
.