Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ VS2013默认初始化与值初始化_C++_C++11_Visual Studio 2013_Constructor_Value Initialization - Fatal编程技术网

C++ VS2013默认初始化与值初始化

C++ VS2013默认初始化与值初始化,c++,c++11,visual-studio-2013,constructor,value-initialization,C++,C++11,Visual Studio 2013,Constructor,Value Initialization,考虑下面的代码 struct B { B() : member{}{}; int member[10]; }; int main() { B b; } VS2013编译器发出以下警告: 警告C4351:新行为:数组“B::member”的元素将被删除 默认初始化1>test.vcxproj-> C:\Users\asaxena2\documents\visualstudio 2013\Projects\test\Debug\test.exe 这是有案可查的 使用C++

考虑下面的代码

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

int main()
{
    B b;
}
VS2013编译器发出以下警告:

警告C4351:新行为:数组“B::member”的元素将被删除 默认初始化1>test.vcxproj-> C:\Users\asaxena2\documents\visualstudio 2013\Projects\test\Debug\test.exe

这是有案可查的

使用C++11,并应用“默认初始化”的概念,意味着不会初始化B.member的元素

但是我相信
成员{}
应该执行值初始化,而不是默认初始化。VS2013编译器是否已损坏

8.5/6美元

默认情况下,初始化类型为
T
的对象意味着: -如果
T
是(可能是cv限定的)类类型(第9条),则调用
T
的默认构造函数(如果
T
没有可访问的默认构造函数,则初始化是错误的)
-如果
T
是数组类型,则默认初始化每个元素
-否则,不执行初始化。
如果程序调用
const
限定类型
T
的对象的默认初始化,
T
应为具有用户提供的默认构造函数的类类型

8.5.1美元

类型为
T
的对象或引用的列表初始化定义如下:
-如果初始值设定项列表没有元素,并且
T
是具有默认构造函数的类类型,则对象值已初始化。
-否则,如果
T
是聚合,则执行聚合初始化(8.5.1)

如果列表中的初始值设定项条款少于集合中的成员,则未明确初始化的每个成员应从空初始值设定项列表中初始化(8.5.4)。[示例:

使用
1
初始化
ss.a
ss.b
使用
“asdf”
ss.c
使用
int()
形式的表达式值进行初始化,即
0
-结束示例]


这似乎是一条措词错误的警告消息(我很惊讶它首先打印了一条警告),但行为是正确的
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 : b.member) std::cout << a << ' ';
    std::cout << std::endl;

    C c;
    for(auto const& a : c.member) std::cout << a << ' ';
    std::cout << std::endl;
}
第二行中的数字是
0xcccc
,VC++编译器在调试模式下用调试模式填充内存。因此,
B::member
被初始化为零,而没有对
C::member
执行初始化


免责声明:我知道读取未初始化的变量是未定义的行为,但这是我能想到的最好证明。

编译器警告不正确;它实际上是按照标准的要求执行值初始化

例如:

#include <iostream>

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

int main() {
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    B &b = *new (a) B;
    std::cout << b.member[9];  // prints '0'
}
#包括
结构B{
B():成员{}{};
国际委员[10];
};
int main(){
inta[10]={0,1,2,3,4,5,6,7,8,9};
B&B=*新(a)B;
标准::cout

C4351意味着您应该检查您的代码…如果您想要新的 行为,这很可能是因为数组已显式添加到 在构造函数的成员初始化列表中,使用pragma 禁用警告。对于大多数情况,新行为应该是正常的 用户


因此,您必须为一行添加
#pragma warning(suppress:4351)
,或为整个文件添加
#pragma warning(disable:4351)

这是一个好问题,但“Visual Studio编译器行为”这是一个可怕的标题。考虑把它变成更有意义的东西。这就是说,你验证了编译器的行为吗?它可能只是一个误导性的警告。@ HVD:改变了它。谢谢斯也检查了反汇编,我看到调用MeSET的成员变量的大小更大的值。因此,有一个明确的调用MeSET。这意味着它是按照标准要求初始化的零。对于较小的n值,它以不同的方式(逐元素)优化和设置0
0 0 0 0 0 0 0 0 0 0
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460
#include <iostream>

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

int main() {
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    B &b = *new (a) B;
    std::cout << b.member[9];  // prints '0'
}