7
votes

In the following example:

#include <iostream>

struct A {
    int z;
    A(std::string) {}
    A() = default;
};

int main() {
    char buf[1000];
    std::fill(buf, buf + 1000, 'x');
    auto a = new(buf) A{};
    std::cerr << "A.z: " << a->z << std::endl;
}

Compiled with GCC 4.8 outputs zero (same behavior with Clang 3.4). This seems to indicate that a is being zero-initialized before the default constructor is called.

But according to value-initialization rules on cppreference.com, the object should not be initialized before the default constructor invocation. Class A qualifies for bullet point #1 under C++11:

1) If T is a class type with at least one user-provided constructor of any kind, the default constructor is called.

Another perhaps useful data point is that if we replace A() = default with A() {} in the above example, no zero-initialization happens as expected. This seems to indicate that bullet point #2 of value initialization is being followed in the initial example which would be wrong:

2) If T is an non-union class type without any user-provided constructors, then the object is zero-initialized and then the implicitly-declared default constructor is called (unless it's trivial)

1

1 Answers

5
votes

The wording that you cite for value initialization in C++11 was considered defective, see Core Working Group DR 1368 and the resolution in Core Working Group DR 1301 that changed the wording (showing additions with bold and deletions with strike through):

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9 [class]) with either no default constructor (12.1 [class.ctor]) or a default constructor that is user-provided or deleted constructor (12.1 [class.ctor]), then the object is default-initialized 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 or deleted default constructor, then the object is zero-initialized and, if T's implicitly-declared default constructor is T has a non-trivial default constructor, that constructor is called. default-initialized;

Some compilers - I believe GCC 4.8 and clang since 3.3ish - have already implemented the resolution of DR 1301.