10

考虑下面的代码

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,则初始化是非良构的); — 如果是数组类型,则每个元素都是默认初始化的; — 否则,不执行初始化。 如果程序要求对具有-qualified type的对象进行默认初始化,则应是具有用户提供的默认构造函数的类类型。T
T

constTT

8.5.1 美元

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

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

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

ss.a使用、 和形式的表达式的值进行初始化1,即. —结束示例] ss.b"asdf"ss.cint()0

4

3 回答 3

8

这似乎是一个措辞不正确的警告信息(我很惊讶它首先打印了一个警告),但行为是正确的。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;
}

如果您在调试模式下编译和运行,则会产生以下输出:

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

第二行中的数字是0xCCCCCCCCVC++ 编译器在调试模式下填充内存的调试模式。因此B::member正在被零初始化,而没有对 执行初始化C::member

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

于 2014-06-09T14:18:47.167 回答
2

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

例子:

#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'
}
于 2014-06-09T14:21:56.520 回答
0

MSDN 页面说:

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

所以你必须#pragma warning (suppress:4351)为一行或#pragma warning (disable:4351)整个文件添加。

于 2016-11-30T21:33:20.537 回答