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
?
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 literal0
(zero) toT
;— 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.