不能 emplace_back() 向量向量上的花括号初始化器
Cannot emplace_back() a braced initializer on a vector of vectors
这与我之前提出的关于在成对向量上使用 emplace_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
因此,由此看来,matrix.emplace_back(std::vector<int>{1,2,3});
似乎是在向量的向量上使用 std::vector<T>::emplace_back
的唯一正确方法,但这似乎与 push_back
相比没有优势。我对这个问题的理解是否正确?
此外,有人可以解释为什么 matrix.emplace_back(3,2)
将一个由 2 组成的大小为 3 的向量插入到矩阵中吗?
在这种情况下,{1, 2, 3}
不能推导为 initializer_list<int>
(这是您要使用的 vector<int>
构造函数所期望的。)所以您需要稍微帮助一下:
matrix.emplace_back(initializer_list<int>{1, 2, 3});
使用 push_back()
时不需要这样做。我不知道确切的细节,但 emplace_back()
是一个函数模板,而 push_back()
不是。模板的推导规则不同(更严格。)并且花括号初始化程序没有类型。因此,它有自己关于类型推导如何工作的特殊规则。
至于效率,这个:
matrix.emplace_back(vector<int>{1, 2, 3});
构造两个向量。 matrix
中的空向量和传递的临时值。临时对象被移动到空向量中。所以真的没那么糟糕。
然而,这:
matrix.emplace_back(initializer_list<int>{1, 2, 3});
只构造一个向量,使用接受 initializer_list 的构造函数。请注意,这里没有创建 "extra" initializer_list
对象。在使用支撑初始化创建任何向量时,无论如何都会创建这样一个对象:
vector<int> vec{1, 2, 3};
这也会创建一个 initializer_list
对象,因为这是向量构造函数所采用的对象。
至于为什么 emplace_back(2,3)
有效,那是因为有一个向量构造函数需要一个大小和一个值。
这与我之前提出的关于在成对向量上使用 emplace_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
因此,由此看来,matrix.emplace_back(std::vector<int>{1,2,3});
似乎是在向量的向量上使用 std::vector<T>::emplace_back
的唯一正确方法,但这似乎与 push_back
相比没有优势。我对这个问题的理解是否正确?
此外,有人可以解释为什么 matrix.emplace_back(3,2)
将一个由 2 组成的大小为 3 的向量插入到矩阵中吗?
在这种情况下,{1, 2, 3}
不能推导为 initializer_list<int>
(这是您要使用的 vector<int>
构造函数所期望的。)所以您需要稍微帮助一下:
matrix.emplace_back(initializer_list<int>{1, 2, 3});
使用 push_back()
时不需要这样做。我不知道确切的细节,但 emplace_back()
是一个函数模板,而 push_back()
不是。模板的推导规则不同(更严格。)并且花括号初始化程序没有类型。因此,它有自己关于类型推导如何工作的特殊规则。
至于效率,这个:
matrix.emplace_back(vector<int>{1, 2, 3});
构造两个向量。 matrix
中的空向量和传递的临时值。临时对象被移动到空向量中。所以真的没那么糟糕。
然而,这:
matrix.emplace_back(initializer_list<int>{1, 2, 3});
只构造一个向量,使用接受 initializer_list 的构造函数。请注意,这里没有创建 "extra" initializer_list
对象。在使用支撑初始化创建任何向量时,无论如何都会创建这样一个对象:
vector<int> vec{1, 2, 3};
这也会创建一个 initializer_list
对象,因为这是向量构造函数所采用的对象。
至于为什么 emplace_back(2,3)
有效,那是因为有一个向量构造函数需要一个大小和一个值。