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

C++14 Uniform Initialization on a Non-Aggregate

本文关键字:初始化 C++14      更新时间:2023-10-16

我使用的是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();
}

如果您的编译器正在执行此操作,则它已损坏。

[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应该首先初始化为0(导致t2.i初始化为0),然后运行默认构造函数。