VS2013默认初始化vs值初始化 [英] VS2013 default initialization vs value initialization

查看:1549
本文介绍了VS2013默认初始化vs值初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑下面的代码

  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: — 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 ]

解决方案

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆