繁体   English   中英

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编译器坏了吗?

$ 7.0 / 6

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

$ 8.5.1

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

如果列表中的initializer-clause少于聚合中的成员,则未显式初始化的每个成员都应从空的初始化列表(8.5.4)初始化。 [ 例如:

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

初始化ss.a1ss.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;
}

如果在Debug模式下编译并运行,则会产生输出:

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

第二行中的数字是0xCCCCCCCC ,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'
}

MSDN页面说:

C4351意味着您应该检查您的代码...如果您想要新的行为,可能是因为该数组已显式添加到构造函数的成员初始化列表中,请使用警告编译指示来禁用该警告。 对大多数用户来说,新行为应该没问题。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM