为什么显式声明的构造函数会阻止使用C++ 11初始化列表进行成员初始化?

Kni*_*chi 3 c++ initializer-list language-lawyer c++11

我想用这样的初始化列表初始化一个结构:

struct S
{
    int a;
    int b;

    // S() : a(0), b(0){}  // uncommenting will cause compile error: 
                           // error C2440: 'initializing' : cannot convert from 'initializer-list' to 'S'

    // S(int aArg, int bArg) : a(aArg), b(bArg) {}    // adding this removes the error
}

int main()
{
    S s{1,2};   // initialise with list
}
Run Code Online (Sandbox Code Playgroud)

有一个很好的理由,为什么显式声明的默认构造函数会导致错误?我认为初始化列表的位置是为了避免程序员编写像第二个构造函数这样繁琐的代码.

Col*_*mbo 7

聚合初始化 - 顾名思义 - 仅适用于聚合.向类中添加一个非平凡的构造函数使其成为非聚合的.[dcl.init.list]/3:

类型T的对象或引用的列表初始化定义如下:
- 如果初始化列表没有元素且T是具有默认构造函数的类类型,则对象是值初始化的.
- 否则,如果T是聚合,则执行聚合初始化(8.5.1).
- 除此以外, […]

聚集体是与阵列或类(第9节)没有用户提供的构造(12.1),[...]
当集合由初始化列表初始化,如在8.5.4规定,初始化器列表的元素取作为聚合成员的初始化者,增加下标或成员顺序.

一旦您的类不再是聚合,list-initialization将查找要调用的构造函数,而不是要初始化的成员.

原因很简单:如果一个类有非平凡的构造函数,那么有效初始化该类类型的对象的唯一方法是调用该对象的一个​​构造函数.在没有相应构造函数的情况下初始化类对象将是一个毁灭性的设计失败.