emplace_back
接受可变参数包作为参数:
template< class... Args >
reference emplace_back( Args&&... args )
当您以以下方式调用时:
emplace_back({1, 2})
,您正在使用一个参数即
{1, 2}
进行调用,而
Args
无法被推断出。这是由于语言的演变方式造成的。在C++中,
{1, 2}
没有类型。它是一个括号括起来的初始化列表,可以用于某些类型的初始化,但是所有初始化都要求已知初始化的类型。这就是为什么
temp_pair = {1,2};
可以工作,因为
temp_pair
的类型已知,并且具有与
(int, int)
匹配的构造函数。
无论如何,
emplace_back
设计初衷并不是像那样使用,而是应该像下面这样使用:
my_vec.emplace_back(1, 2);
请注意,即使这些起作用:
my_vec.emplace_back(std::pair<int, int>{1, 2});
my_vec.emplace_back(temp_pair);
它们不应该被使用。它们在push_back上没有任何优势。emplace_back的整个意义是避免创建临时T。上述调用都会创建临时std::pair。
但我认为你可以在任何你有push_back的地方使用emplace_back
在大多数情况下,这是正确的。至少这是意图。而且你确实可以在你的情况下使用它。只需要稍微调整一下语法。所以,代替push_back({1, 2}),你可以使用emplace_back(1, 2)。
有一种情况,很遗憾,你不能使用emplace_back:聚合体。
struct Agg
{
int a, b;
};
auto test()
{
Agg a{1, 2};
std::vector<Agg> v;
v.emplace_back(1, 2);
}
如果没有为Agg
添加构造函数,这段代码是无法正常工作的。这被认为是标准中的一个缺陷,但不幸的是他们找不到一个好的解决方案。问题出在花括号初始化的方式上,如果在通用代码中使用它,你可能会漏掉一些构造函数。想了解更多细节,请查看这篇优秀的文章:为什么可以用花括号初始化聚合结构体,但不能使用与花括号初始化相同的参数列表进行插入?
({1,2})
不起作用? - 24n8