emplace_back 内的聚合初始化

You*_*aid 1 c++ aggregate-initialization emplace

在下面的代码中,我尝试使用 emplace_back 进行聚合初始化。这里的问题是 emplace_back 接受构造函数参数并直接在向量中构造对象,我想知道是否在 a 上调​​用了复制构造函数A{1,2,3}。但是,为了使聚合初始化起作用,该结构不应具有用户定义的构造函数。你知道幕后发生了什么吗?

#include <iostream>
#include <vector>

struct A {
    int x, y, z;
    /*A(int x, int y, int z) : x(x), y(y), z(z) 
    {
        std::cout << "ctor called\n";
    }
    A(const A& other) : x(other.x), y(other.y), z(other.z) {
        std::cout << "copy ctor called\n";
    }*/
};

int main() {

    std::vector<A> vec;

    vec.emplace_back(A{1, 2, 3});

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Jan*_*tke 5

emplace_back正如您所说,将直接在向量中构造对象。但是,您已经A{1, 2, 3}在调用站点构造了一个临时对象,因此向量中的对象将被复制/移动构造,总共有两个对象。注意:

  • 聚合类型没有将其成员初始化为参数列表的构造函数,但如果可能,它们具有隐式定义的复制/移动构造函数
  • A{1, 2, 3}没有调用任何构造函数;它执行聚合初始化

该表达式A{1, 2, 3}是纯右值,将通过右值引用传递给emplace_backA然后,将调用 的隐式定义的移动构造函数,而不是复制构造函数。

提供复制构造函数未声明移动构造函数

如果取消代码中复制构造函数的注释,则会调用复制构造函数,因为未声明移动构造函数。您必须添加:

A(A&&) = default;
Run Code Online (Sandbox Code Playgroud)

然后,将调用移动构造函数,而不是复制构造函数。此外,定义此构造函数会使类型成为非聚合类型,因此您现在需要定义一个构造函数,A(int, int, int)因为聚合初始化不再可能。

C++20 注释

在 C++20 中,您也可以使用括号初始化聚合。emplace_back这允许您像A有构造函数一样使用A(int, int, int)

struct A {
    int x, y, z;
};

std::vector<A> vec;
vec.emplace_back(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)