【问题标题】:Why doesn't VS2013 zero-initialize this struct? [duplicate]为什么 VS2013 不对这个结构进行零初始化? [复制]
【发布时间】:2015-01-21 11:11:44
【问题描述】:

使用 Microsoft Visual Studio Ultimate 2013 更新 4 和以下代码:

#include <iostream>

auto main() -> int {
    struct Base { int a; };
    struct Derived : Base { int b; };

    auto foo = Derived();

    std::cout << foo.a << " " << foo.b;
}

我得到这个输出:

-858993460 -858993460

但我期待:

0 0

为什么foo 没有初始化为零?

【问题讨论】:

  • 您是否尝试过先搜索答案?
  • 因为不应该这样。
  • 但是根据标准,成员应该是零初始化的。并且 gcc/clang 根据需要对对象进行零初始化。
  • @Dialectus:恐怕这他的尝试。
  • @ForEveR 你有指向标准中相关条款的指针吗?

标签: c++ visual-studio-2013


【解决方案1】:

应该初始化为零,看起来像MSVC bug。 因为实际上你的代码是这样的

Derived foo{Derived()};

然后将在使用() 初始化的临时对象上调用复制/移动构造函数。

n3376 8.5/10

一个对象,其初始值设定项是一组空括号,即 (), 应该是值初始化的。

n3376 8.5/7

对 T 类型的对象进行值初始化意味着:

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

n3376 8.5/5

对 T 类型的对象或引用进行零初始化意味着:

如果 T 是(可能是 cv 限定的)非联合类类型,每个 非静态数据成员和每个基类子对象是 零初始化和填充被初始化为零位;

【讨论】:

  • 其实和Derived foo( (Derived()) );是一样的。没有额外的括号,你会遇到最尴尬的解析问题(并声明一个函数)。
  • 哇,我在这里很容易损失 100 美元。 “空括号均值初始化”规则是否始终存在,或者它是否与 auto 和大括号一起引入?我尝试了 VS 2013 vs gcc 4.9.2; VS 不会初始化结构体,gcc 会。
  • 我也对是否确实会在临时对象上调用复制/移动构造函数感兴趣。我原以为总会有一个直接初始化的对象,就像int i=0;
  • @PeterSchneider 这条规则在 C++11 之前。这不是直接初始化,而是复制初始化,但编译器可以(并且将)优化它。
【解决方案2】:

你的结构没有构造函数,所以默认创建一个。

结构的默认构造函数将为每个成员调用默认构造函数。

int 的默认构造函数不会对其进行初始化。所以intmemeber 会包含随机数据。

将构造函数添加到您的结构并初始化成员。像这样:

struct Base
{
    Base(): a(0) {}
    int a;
};

【讨论】:

  • OP 询问为什么它会发生,而不是如何解决它。
  • @HolyBlackCat 我认为这篇文章很好地解释了“为什么”。问题是它是否正确(我认为直到我阅读了 ForEverR 的帖子)。是这样吗??
  • 我认为不是。如果我没记错的话,如果您在初始化结构类型的变量时没有明确要求默认构造函数(如果此结构只有原始类型(或其他类似结构)的字段并且没有用户提供的初始化构造函数这些字段),则字段未初始化为 0。看到这个:ideone.com/SkHTxi 它打印垃圾。将第 9 行末尾的Derived; 替换为Derived();,它将打印0s。
  • 这意味着 Michał 是错误的,VC 也是错误的(虽然解决方法可行)。
猜你喜欢
  • 1970-01-01
  • 2021-10-23
  • 2012-12-03
  • 1970-01-01
  • 2016-03-30
  • 1970-01-01
  • 1970-01-01
  • 2021-12-16
  • 2013-10-14
相关资源
最近更新 更多