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:

  1. Fill sizeof(B) with zeroes
  2. 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.