不能在向量向量上 emplace_back() 一个带支撑的初始值设定项

Iam*_*non 5 c++ stl vector push-back emplace

这与我之前提出的关于emplace_back在成对向量上使用的问题有些相关。将一对插入 std::vector 时,emplace_back() 与 push_back

现在我的问题与emplace_back在向量向量上使用有关。

这是我用评论质疑的代码

std::vector<std::vector<int>> matrix;

matrix.emplace_back({1,2,3}); //doesn't compile

matrix.emplace_back(1,2,3); //doesn't compile

matrix.push_back({1,2,3}); //works and does what is expected (insert a vector made of {1,2,3} into matrix);

matrix.emplace_back(std::vector<int>{1,2,3});   //works but 
//defeats the purpose of using emplace_back since this makes a copy
//and is thus equivalent to push_back in this case?

matrix.emplace_back(3,2) //this compiles, 
//but it seems to insert a vector of size 3 made of 2s into the matrix. 
//not actually sure why it does this

Run Code Online (Sandbox Code Playgroud)

因此,matrix.emplace_back(std::vector<int>{1,2,3});由此看来,似乎是在std::vector<T>::emplace_back向量向量上使用的唯一正确方法,但这似乎与push_back. 我对这个问题的理解是否正确?

另外,有人可以解释为什么matrix.emplace_back(3,2)在矩阵中插入一个由 2s 组成的大小为 3 的向量吗?

Nik*_* C. 5

在这种情况下无法{1, 2, 3}推断出initializer_list<int>(这是vector<int>您想要使用的构造函数所期望的。)因此您需要稍微帮助它:

matrix.emplace_back(initializer_list<int>{1, 2, 3});
Run Code Online (Sandbox Code Playgroud)

使用时不需要这样做push_back()。我不知道确切的细节,但它emplace_back()是一个函数模板,而push_back()不是。模板的推导规则不同(更严格)。并且花括号初始化器没有类型。因此,它对于类型推导的工作方式有自己的特殊规则。

至于效率,这个:

matrix.emplace_back(vector<int>{1, 2, 3});
Run Code Online (Sandbox Code Playgroud)

构造两个向量。中的空向量matrix以及传递的临时向量。临时值被移动到空向量中。所以这真的没那么糟糕。

然而,这个:

matrix.emplace_back(initializer_list<int>{1, 2, 3});
Run Code Online (Sandbox Code Playgroud)

使用接受初始值设定项列表的构造函数仅构造一个向量。请注意,此处没有initializer_list创建“额外”对象。当使用花括号初始化创建任何向量时,无论如何都会创建这样的对象:

vector<int> vec{1, 2, 3};
Run Code Online (Sandbox Code Playgroud)

这也会创建一个initializer_list对象,因为这就是向量构造函数所采用的。

至于为什么emplace_back(2,3)有效,那是因为有一个向量构造函数需要一个大小和一个值。