指定构造函数时列表初始化的不同行为

Mel*_*ato 2 c++ initialization c++17

我有这样的代码,例如:

class A {
public:
    int x;

    A() {
        std::cout << "Constructor Called !" << std::endl;
    }
    A(int y):x(y) {
        std::cout << "Constructor Param Called !" << std::endl;
    }

    A(const A& copy) {
        std::cout << "Copy Constructor Called !" << std::endl;
    }
}

class B {
public:
    A value;
    //B(const A& val) : value(val){}
}

int main(){
    B b { A(22)};
}
Run Code Online (Sandbox Code Playgroud)

如果我注释掉 B 构造函数,则输出只是“调用构造函数参数”,但如果我取消注释 B 构造函数,则输出将是“调用构造函数参数”和“调用复制构造函数”。我的问题:

  1. 如果我注释掉构造函数,为什么输出会不同?(我读过有关聚合类和聚合初始化的内容,是这样吗?)
  2. 聚合初始化直接初始化有什么区别?

0x4*_*2D2 6

当您删除用户提供的构造函数时BB成为聚合。因此,执行聚合初始化时,类的每个元素都是从初始化器列表的元素复制初始化的。由于A(22)是 与 的元素属于同一类的纯右值B,因此会发生复制省略,其中值直接存储到对象中,而不调用任何复制构造函数。这是 C++17 中的新内容。

当您声明 的构造函数时B,它不再是聚合,因此在进行初始化时会考虑构造函数。

=直接初始化只是意味着在初始化对象时没有任何迹象。聚合初始化是在初始化聚合时发生的事情,您可以查看cppreference 上的定义。