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: — ifT
is a (possibly cv-qualified) class type (Clause 9), the default constructor forT
is called (and the initialization is ill-formed ifT
has no accessible default constructor);
— ifT
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 aconst
-qualified typeT
,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 andT
is a class type with a default constructor, the object is value-initialized.
— Otherwise, ifT
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
with1
,ss.b
with"asdf"
, andss.c
with the value of an expression of the formint()
, that is,0
. —end example ]
The MSDN page says:
So you have to add
#pragma warning (suppress:4351)
for one line or#pragma warning (disable:4351)
for the whole file.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 ofint
turns into zero initialization. This can be demonstrated using the following:If you compile and run in Debug mode this results in the output:
The numbers in the second line are
0xCCCCCCCC
, the debug pattern the VC++ compiler fills memory with in Debug mode. ThusB::member
is being zero-initialized, while no initialization is performed forC::member
.Disclaimer: I know that reading from an uninitialized variable is undefined behavior, but this is the best proof I could come up with.
The compiler warning is incorrect; it is actually performing value-initialization as required by the standard.
Example: