将一对插入std :: vector时emplace_back()vs push_back [英] emplace_back() vs push_back when inserting a pair into std::vector

查看:126
本文介绍了将一对插入std :: vector时emplace_back()vs push_back的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我定义了以下内容

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 have push_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆