【问题标题】:A BIG bug of VC++? Why does initializer-list not value-initialize a struct?VC++ 的一个大错误?为什么初始化器列表不对结构进行值初始化?
【发布时间】:2012-12-03 22:48:30
【问题描述】:

C++11 标准 8.5.4.3 说:

“如果初始化列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。”

struct A
{
    int get() { return i; }

private:
    int i;
};

int main()
{
    A a = {};

    int n = a.get();
    cout << n << endl;
    // n is a random number rather than 0

    return 0;
}

这是 VC++ 的错误吗?我的 VC++ 是 2012 年 11 月最新的 CTP。

【问题讨论】:

  • 编译器优化不应破坏 C++ 标准的规定。所以我认为这与优化无关。
  • @KillianDS,请查看我修改后的帖子
  • 加上std::cout &lt;&lt; n &lt;&lt; std::endl;会打印什么?
  • 打印出 0xCCCCCCCC。
  • 我在 g++ 4.6.3 中得到了类似的行为,但据我所知,这种行为是错误的。您遇到的情况似乎是第 8.5.7 节的第二种情况,这表明会发生零初始化。

标签: c++ c++11 initialization aggregate initializer-list


【解决方案1】:

8.5p8 涵盖了非聚合类类型的值初始化。在您的情况下,(非联合)类具有隐式声明的默认默认无参数构造函数(12.1p5),它不会被删除并且是微不足道的(同上)。因此 8.5p8 的第二个要点适用:

— 如果T 是一个(可能是 cv 限定的)非联合类类型,没有用户提供或删除的默认构造函数,则该对象为零初始化,并且如果 T 具有非平凡的默认值构造函数,默认初始化;

所以A应该被零初始化,程序应该打印0

关于以下节目:

struct A { int get() { return i; } private: int i; };
#include <iostream>
int main() {
    char c[sizeof(A)];
    new (c) int{42};
    std::cout << (new (c) A{})->get() << '\n';
}

gcc-4.7.2 正确输出0; gcc-4.6.3 错误输出42; clang-3.0 非常疯狂并输出垃圾(例如574874232)。

【讨论】:

  • 从什么时候开始零或默认初始化一个类会触及任何其他未初始化的成员?
  • @LightnessRacesinOrbit 至少从 C++11 [dcl.init] /5: "[...] — 如果 T 是一个(可能是 cv-限定)非联合类类型,每个非静态数据成员和每个基类子对象都初始化为零,填充初始化为零位;[...]"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 2015-01-13
  • 1970-01-01
  • 2017-03-23
  • 1970-01-01
相关资源
最近更新 更多