c++visual-c++constructordefault-constructorvisual-c++-2013

Why does "ctor() = default" change behavior when other constructors are present?


Why does

struct wrapper
{
    explicit wrapper(void *);
    wrapper() = default;
    int v;
};

int main() { return wrapper().v; }  // You should run this in Debug mode

return 0xCCCCCCCC, whereas

struct wrapper { wrapper() = default; int v; };
int main() { return wrapper().v; }

and

struct wrapper { int v; };
int main() { return wrapper().v; }

both return 0?


Solution

  • During value-initialization, if T is a class type without a user-provided or deleted default-constructor, then the object is zero-initialized (§8.5/8.2). This is indeed the case with wrapper.

    Your first example matches the third case for zero-initialization (§8.5/6.1, emphasis mine)

    — if T is a scalar type (3.9), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;

    if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class sub-object 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

    So in your first example, v should be zero-initialized. This looks like a bug.

    In your second and third example you no longer have a user-provided constructor, but you do have a default-constructor that isn't user-provided or deleted so your example still falls into the third case for zero-initialization, which is to zero-initialize each non-static data member. VS is correct there.