Member not zeroed, a clang++ bug?

c++, c++11, clang, clang++

Solution

Clang is correct, per the C++11 standard plus relevant DRs

In the original C++11 specification, `B{}` would perform value-initialization, resulting in `a.i` being zero-initialized. This was a change in behavior compared to C++98 for cases like

B b = {};

... which were handled as aggregate initialization in C++98 but treated as value-initialization in C++11 FDIS.

However, the behavior in this case was changed by core issue 1301, which restored the C++98 behavior by mandating that aggregate initialization is used whenever an aggregate is initialized by a braced-init-list. Since this issue is considered a DR, it is treated as de facto applying to earlier revisions of the C++ standard, so a conforming C++11 compiler would be expected to perform aggregate initialization here rather than value-initialization.

Ultimately, it's a bad idea to rely on value-initialization to initialize your data members, especially for a class that has user-provided constructors.

Problem

Consider the following code: ``` class A { public: int i; A() {} }; class B { public: A a; int i; }; int main() { B* p = new B {}; std::cout << p->i << " " << p->a.i << "\n"; } ``` Compiled with -std=c++11 in clang++, `p->i` turns out to be zero, but `p->a.i` doesn't. Shouldn't the whole object be zeroed as long as its class doesn't have user-provided constructor? EDIT: Since there are some extensive discussion in the comments, I think it's better to add some excerpt from the standard here: 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. - if `T` is an array type, then each element is value-initialized; - otherwise, the object is zero-initialized. To zero-initialize an object or reference of type T means: - if `T` is a scalar type (3.9), the object is set to the value `0` (zero), taken as an integral constant expression, converted to `T`; - 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; - 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; - if `T` is an array type, each element is zero-initialized; - if `T` is a reference type, no initialization is performed. The second bullet of each applies here.

Original source