VS2013默认初始化vs值初始化 [英] VS2013 default initialization vs value initialization
问题描述
请考虑下面的代码
struct B
{
B():member {} { };
int member [10];
}
int main()
{
B b;
}
VS2013编译器提供以下警告:
警告C4351:新行为:数组'B :: member'的元素将是
默认初始化1> test.vcxproj - >
C: \\Users\asaxena2\documents\visual studio
2013\Projects\test\Debug\test.exe
这是此处的说明
使用C ++ 11,并应用默认初始化的概念,意味着B.member的元素不会被初始化。
但我相信 member {}
应该执行值初始化而不是默认初始化。是VS2013编译器坏了吗?
$ 8.5 / 6
类型
T
的对象意味着:
- 如果T
是(可能是cv限定的)类类型(条款9),调用T
的默认构造函数(如果T
没有;
- 如果T
是数组类型,每个元素都默认初始化;
-
如果程序调用const
- 限定类型T
,T
是一个具有用户提供的默认构造函数的类类型。
$ 8.5.1
类型
T
定义如下:\\
- 如果初始化器列表没有元素,并且T
- 否则,如果T
是聚合,则执行聚合初始化(8.5.1)
如果列表中的初始化子句数少于聚合中的成员数,那么没有显式初始化的每个成员都应该从一个空的初始化列表.4)。 [示例:
struct S {int a; const char * b; int c; };
S ss = {1,asdf};
使用<$ c初始化
ss.a
$ c> 1 ,ss.b
与asdf
$ c> cs.c 与int()
形式的表达式的值,即0
。 -end example ]
B :: member
正在进行值初始化,对于 int
的数组,变为零初始化。这可以通过以下方式证明: #include< iostream>
struct B
{
B():member {} {};
int member [10];
}
struct C
{
C(){};
int member [10];
}
int main()
{
B b;
for(auto const& a:bmember)std :: cout<< a<<< '';
std :: cout<< std :: endl;
C c;
for(auto const& a:cmember)std :: cout<< a<< '';
std :: cout<< std :: endl;
}
如果您在调试模式下编译并运行导致输出:
0 0 0 0 0 0 0 0 0 0
-858993460 -858993460 -858993460 - 858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
第二行中的数字为 0xCCCCCCCC
,调试模式VC ++编译器在调试模式下填充内存。因此, B :: member
正在进行零初始化,而不对 C :: member
执行初始化。 p>
免责声明:我知道从未初始化的变量读取未定义的行为,但这是最好的证明。
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 ]
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.
这篇关于VS2013默认初始化vs值初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!