关于push_back和emplace_back之间的区别,我有点困惑。

void emplace_back(Type&& _Val);
void push_back(const Type& _Val);
void push_back(Type&& _Val);

由于有一个push_back重载取右值引用,我不太清楚emplace_back的目的是什么?


当前回答

这里显示了push_back和emplace_back的代码。

http://en.cppreference.com/w/cpp/container/vector/emplace_back

您可以在push_back上看到移动操作,而在emplace_back上看不到。

其他回答

emplace_back的特定用例:如果您需要创建一个临时对象,然后将其推入容器,请使用emplace_back而不是push_back。它将在容器内就地创建对象。

注:

上面例子中的Push_back将创建一个临时对象并移动它 放进容器里。然而,用于emplace_back的in-place结构将更多 性能比构造然后移动对象(通常涉及一些复制)。 一般来说,在所有情况下都可以使用emplace_back而不是push_back,没有太多问题。(见异常)

emplace_back的优化可以在下一个示例中演示。

对于emplace_back,将调用构造函数A (int x_arg)。和 首先调用push_back A (int x_arg),然后调用move A (A &&rhs)。

当然,构造函数必须被标记为显式的,但对于当前的示例来说,删除显式是很好的。

#include <iostream>
#include <vector>
class A
{
public:
  A (int x_arg) : x (x_arg) { std::cout << "A (x_arg)\n"; }
  A () { x = 0; std::cout << "A ()\n"; }
  A (const A &rhs) noexcept { x = rhs.x; std::cout << "A (A &)\n"; }
  A (A &&rhs) noexcept { x = rhs.x; std::cout << "A (A &&)\n"; }

private:
  int x;
};

int main ()
{
  {
    std::vector<A> a;
    std::cout << "call emplace_back:\n";
    a.emplace_back (0);
  }
  {
    std::vector<A> a;
    std::cout << "call push_back:\n";
    a.push_back (1);
  }
  return 0;
}

输出:

call emplace_back:
A (x_arg)

call push_back:
A (x_arg)
A (A &&)

Emplace_back不应该接受vector::value_type类型的参数,而应该接受转发给附加项的构造函数的可变参数。

template <class... Args> void emplace_back(Args&&... args); 

可以传递一个value_type,它将被转发给复制构造函数。

因为它转发参数,这意味着如果你没有右值,这仍然意味着容器将存储一个“复制”的副本,而不是一个移动的副本。

 std::vector<std::string> vec;
 vec.emplace_back(std::string("Hello")); // moves
 std::string s;
 vec.emplace_back(s); //copies

但是上面的功能应该与push_back功能相同。它可能更适合以下用例:

 std::vector<std::pair<std::string, std::string> > vec;
 vec.emplace_back(std::string("Hello"), std::string("world")); 
 // should end up invoking this constructor:
 //template<class U, class V> pair(U&& x, V&& y);
 //without making any copies of the strings

还有一个关于列表的例子:

// constructs the elements in place.                                                
emplace_back("element");

// creates a new object and then copies (or moves) that object.
push_back(ExplicitDataType{"element"});

这里显示了push_back和emplace_back的代码。

http://en.cppreference.com/w/cpp/container/vector/emplace_back

您可以在push_back上看到移动操作,而在emplace_back上看不到。