将一对插入std :: vector时emplace_back()vs push_back [英] emplace_back() vs push_back when inserting a pair into std::vector
问题描述
我定义了以下内容
std::vector<std::pair<int,int> > my_vec;
my_vec.push_back( {1,2} ); //this works
my_vec.emplace_back( {1,2} ); // this doesn't work
std::pair<int,int> temp_pair = {1,2};
my_vec.emplace_back( temp_pair ); //this works
我正在使用c ++ 11进行编译。第三行是有问题的,但是我认为您可以在有 push_back()
的任何地方使用 emplace_back()
,但是这显然是错误的。为什么第三行不起作用?
I am compiling with c++11. The third line is problematic, but I thought you can use emplace_back()
anywhere that you have push_back()
, but this is apparently wrong. Why does the third line not work?
推荐答案
emplace_back
将可变参数包作为参数:
emplace_back
takes a variadic parameter pack as argument:
template< class... Args >
reference emplace_back( Args&&... args );
当您这样称呼时: emplace_back({1,2})
您用一个参数调用它,即 {1,2}
和 Args
无法推论。那是因为语言的发展。在C ++中, {1,2}
没有类型。它是一个用括号括起来的init-list,可以在某些类型的初始化中使用,但是所有这些都需要知道初始化的类型。这就是为什么 temp_pair = {1,2};
起作用的原因,因为 temp_pair
的类型是已知的并且具有构造函数匹配(int,int)
。
When you call it like this: emplace_back({1, 2})
you are calling it with one argument i.e. {1, 2}
and the Args
cannot be deduced. That is because of how the language has evolved. In C++ {1, 2}
doesn't have a type. It is a brace enclosed init-list and can be used in certain types of initializations, but all require the type of the initialized to be known. That is why temp_pair = {1,2};
works, because the type of temp_pair
is know and has a constructor matching (int, int)
.
反正 emplace_back
不应该这样使用,而是这样:
Anyway emplace_back
wasn't supposed to be used like that, but like this instead:
my_vec.emplace_back(1, 2);
也请注意,即使这些工作有效:
Also please note that even if these work:
my_vec.emplace_back(std::pair<int, int>{1, 2});
my_vec.emplace_back(temp_pair);
不应该使用它们。与push_back相比,它们没有任何优势。 emplace_back
的全部要点是避免创建临时的 T
。上面的调用全部创建了临时 std :: pair< int,int>
。
They shouldn't be used. They add no advantage over push_back. The whole point of emplace_back
is to avoid creating a temporary T
. The above calls all create the temporary std::pair<int, int>
.
,但我想您可以在有
push_back的任何地方使用
emplace_back()
()
but I thought you can use
emplace_back()
anywhere that you havepush_back()
在大多数情况下是正确的。至少那是意图。而且您确实可以在自己的Cese中使用它。您只需要稍微调整一下语法即可。因此,可以使用 emplace_back(1、2)
代替 push_back({1,2})
。
For the most part that's correct. At least that was the intention. And you can indeed use it in your cese. You just have to adjust the syntax a little. So instead of push_back({1, 2})
you can use emplace_back(1, 2)
.
不幸的是,有些情况下您不能使用 emplace_back
:聚合。
There is a situation where unfortunately you can't use emplace_back
: aggregates.
struct Agg
{
int a, b;
};
auto test()
{
Agg a{1, 2}; // ok, aggregate initialization
std::vector<Agg> v;
v.emplace_back(1, 2); // doesn't work :(
}
除非您添加 Agg
的构造函数,这被认为是标准中的一个开放缺陷,但是不幸的是,他们找不到一个好的解决方案,问题在于括号初始化初始化的工作方式如果您在通用代码中使用它,可能会错过一些构造函数。有关所有细节的信息,请查看以下精彩文章:为什么要进行聚集
This doesn't work unless you add a constructor for Agg
. This is considered an open defect in the standard, but unfortunately they can't find a good solution to this. The problem is with how brace init initialization works and if you use it in generic code you can miss some constructors. For all the nitty-gritty details check this great post: Why can an aggreggate struct be brace-initialized, but not emplaced using the same list of arguments as in the brace initialization?
这篇关于将一对插入std :: vector时emplace_back()vs push_back的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!