user3701522 user3701522 - 3 days ago 4
C++ Question

VS2013 default initialization vs value initialization

Consider the code below

struct B
{
B() : member{}{};
int member[10];
};

int main()
{
B b;
}


VS2013 compiler gives the following warning:


warning C4351: new behavior: elements of array 'B::member' will be
default initialized 1> test.vcxproj ->
C:\Users\asaxena2\documents\visual studio
2013\Projects\test\Debug\test.exe


This is documented here

With C++11, and applying the concept of 'default initialization', means that elements of B.member will not be initialized.

But I believe that
member{}
should perform value initialization and not default initialization. Is the VS2013 compiler broken?

$8.5/6


To default-initialize an object of type
T
means:
— if
T
is a (possibly cv-qualified) class type (Clause 9), the default constructor for
T
is called (and the initialization is ill-formed if
T
has no accessible default constructor);

— if
T
is an array type, each element is default-initialized;

— otherwise, no initialization is performed.

If a program calls for the default initialization of an object of a
const
-qualified type
T
,
T
shall be a class type with a user-provided default constructor.


$8.5.1


List-initialization of an object or reference of type
T
is defined as follows:

— If the initializer list has no elements and
T
is a class type with a default constructor, the object is value-initialized.

— Otherwise, if
T
is an aggregate, aggregate initialization is performed (8.5.1).

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list (8.5.4). [ Example:

struct S { int a; const char* b; int c; };
S ss = { 1, "asdf" };


initializes
ss.a
with
1
,
ss.b
with
"asdf"
, and
ss.c
with the value of an expression of the form
int()
, that is,
0
. —end example ]


Answer

It seems to be an incorrectly worded warning message (and I'm surprised it is printing a warning in the first place), but the behavior is correct. B::member is being value initialized, which for an array of int turns into zero initialization. This can be demonstrated using the following:

#include <iostream>

struct B
{
    B() : member{}{};
    int member[10];
};

struct C
{
    C() {};
    int member[10];
};

int main()
{
    B b;
    for(auto const& a : b.member) std::cout << a << ' ';
    std::cout << std::endl;

    C c;
    for(auto const& a : c.member) std::cout << a << ' ';
    std::cout << std::endl;
}

If you compile and run in Debug mode this results in the output:

0 0 0 0 0 0 0 0 0 0
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

The numbers in the second line are 0xCCCCCCCC, the debug pattern the VC++ compiler fills memory with in Debug mode. Thus B::member is being zero-initialized, while no initialization is performed for C::member.

Disclaimer: I know that reading from an uninitialized variable is undefined behavior, but this is the best proof I could come up with.

Comments