使用初始值设定项列表放置向量

问题描述 投票:0回答:3

我有一个

std::vector<std::vector<double>>
,想在它的末尾添加一些元素,所以这是我的尝试:

std::vector<std::vector<double> > vec;
vec.emplace_back({0,0});

但是这不能编译,而以下代码可以:

std::vector<double> vector({0,0});

为什么 emplace_back 不能在这个位置构造元素?或者我做错了什么?

c++ stdvector emplace stdinitializerlist
3个回答
33
投票

前面的答案提到,当您在线构建向量并放置它时,您可以获得要编译的代码。 然而,这意味着您在临时向量上调用移动构造函数,这意味着您没有就地构建向量,而这就是使用

emplace_back
而不是
push_back
的全部原因。

相反,您应该将初始值设定项列表转换为

initializer_list
,如下所示:

#include <vector>
#include <initializer_list>

int main()
{
    std::vector<std::vector<int>> vec;
    vec.emplace_back((std::initializer_list<int>){1,2});
}

13
投票

模板推导无法猜测你的大括号括起来的初始化列表应该是一个向量。你需要明确:

vec.emplace_back(std::vector<double>{0.,0.});

请注意,这构造了一个向量,然后使用

std::vector
的移动复制构造函数将其移动到新元素中。所以在这种特殊情况下,它比
push_back()
没有优势。 @TimKuipers 的回答显示了解决这个问题的方法。


3
投票

这里实际上有两个问题:数字类型转换和模板参数推导。

std::vector<double>
构造函数可以为其
int
构造函数使用大括号列表(甚至是
std::vector<double>(std::initializer_list<double>)
)。 (但请注意,
std::initializer_list<int>
不会隐式转换为
std::initializer_list<double>

emplace_back()
无法从大括号表达式构造元素,因为它是使用完美转发的模板。标准禁止编译器推断
{0,0}
的类型,因此
std::vector<double>::emplace_back<std::initializer_list<double>>(std::initializer_list<double>)
不会被编译为
emplace_back({})

其他答案指出

emplace_back
can 可以编译为
std::initializer_list<vector::value_type>
类型的参数,但不会直接从
{}
表达式推导出该类型。

作为将参数转换为

emplace_back
的替代方法,您可以先构造参数。正如 Meyers 的 Item 30 (Effective Modern C++) 中所指出的,允许
auto
将大括号表达式的类型推导为
std::initializer_list<T>
,并且允许完美转发来推导由
 推导类型的对象的类型auto

std::vector<std::vector<double> > vec;
auto double_list = {0., 0.}; // int_list is type std::initializer_list<int>
vec.emplace_back(double_list); // instantiates vec.emplace_back<std::initializer_list<double>&>

emplace_back
通过调用
vec
将元素添加到
std::vector<double>(std::forward<std::initializer_list<double>>(double_list))
,从而触发
std::vector<double>(std::initializer_list<double>)
构造函数。

参考:第 17.8.2.5 节第 5.6 项表示 this 是一个非推导上下文,用于第 17.8.2.1 节第 1 项下模板参数推导的目的。

更新:此答案的早期版本错误地暗示可以提供

std::initializer_list<int>
来代替
std::initializer_list<double>

© www.soinside.com 2019 - 2024. All rights reserved.