C++ 14非聚合上的统一初始化

Sel*_*mAI 5 c++ uniform-initialization c++14

我正在使用Visual C++ 2013.当类是聚合时,它是零初始化的.当它是非聚合时,它似乎是默认初始化并且不确定.这是为什么?

#include <iostream>

using namespace std;

class Test_1
{
public:
    int i;
    void f(){};
};

class Test_2
{
public:
    int i;
    virtual void f(){};
};

int main()
{
    Test_1 t1{};
    Test_2 t2{};

    cout<<t1.i<<endl; //0
    cout<<t2.i<<endl; //-858993460

    getchar();
}
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 4

如果你的编译器这样做了,它就坏了。

[dcl.init.list]/p3(所有引用均来自N4140):

对象或类型引用的列表初始化T定义如下:

  • 如果T是聚合,则执行聚合初始化 (8.5.1)。
  • 否则,如果初始值设定项列表没有元素并且T是具有默认构造函数的类类型,则该对象将被值初始化。
  • [...]

[dcl.init]/p8:

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

  • 如果T是一个(可能是 cv 限定的)类类型(第 9 条),没有默认构造函数 (12.1) 或用户提供或删除的默认构造函数,则该对象被默认初始化;
  • 如果T是一个(可能是 cv 限定的)类类型,没有用户提供或删除的默认构造函数,则该对象被零初始化并检查默认初始化的语义约束,并且如果 T 有一个非平凡的默认构造函数,该对象是默认初始化的;
  • 如果 T 是数组类型,则每个元素都是值初始化的;
  • 否则,该对象将被零初始化。

Test_2不是聚合,因此t2应该已进行值初始化。反过来,由于Test_2的默认构造函数不是用户提供的,t2因此应该首先进行零初始化(导致t2.i初始化为 0),然后运行默认构造函数。

  • 非平凡类的值初始化在 VC++ 中确实被破坏了,而且一直如此。遗憾的是,尽管初始化语义本质上是必要的,但目前还没有解决办法。[此处](https://connect.microsoft.com/VisualStudio/feedback/details/746973/in Correct-c-11-value-initialization-for-type-with-implicitly-declared-but-non-trivial-default-构造函数)是许多提交的错误报告之一,我见过的所有错误报告都以“延迟”形式关闭。[在某些情况下,甚至聚合初始化也不正确。](https://connect.microsoft.com/VisualStudio/Feedback/Details/956553) (5认同)