Member not zeroed, a clang++ bug?

前端 未结 4 1365
孤街浪徒
孤街浪徒 2020-12-15 08:36

Consider the following code:

class A {
public:
    int i;
    A() {}
};

class B {
public:
    A a;
    int i;
};

int main() {
    B* p = new B {};
    std:         


        
4条回答
  •  刺人心
    刺人心 (楼主)
    2020-12-15 09:05

    It is not a compiler bug, it is a bug in your code. The compiler seems to be implementing the C++03 behaviour, but this has crucially changed in C++11.

    These are some relevant quotes from the C++03 and C++11 standards

    In C++03:

    To value-initialize an object of type T means:

    — if T is a class type (clause 9) with a user-declared 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 non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;

    (emphasis mine)

    In C++11:

    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.

    and

    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;

    Note: The following only applies to C++03:

    Either remove A's user-provided constructor, or change it to

    A() : i() {}
    

    When you value-initialize a B here,

    B* p = new B {};
    

    it value-initializes its data members. Since A has a default constructor, the value-initialization results in a call to that. But that constructor does not explicitly initialize A::i, so it gets default-initialized, which for an int means no initialization is performed.

    If you had not provided a default constructor for A, then the data member would get zero-initialized when an A is value-initialized.

提交回复
热议问题