为什么不能重载push_back来完成emplace_back的工作?

时间:2011-08-09 17:57:06

标签: c++ c++11

首先,我知道this question,但我不相信我会问同样的事情。

我知道std::vector<T>::emplace_back 做了什么 - 我理解为什么我会在push_back()上使用它。它使用可变参数模板,允许我将多个参数转发给新元素的构造函数。

但我不明白为什么C ++标准委员会认为需要一个新的成员函数。为什么他们不能简单地扩展push_back()的功能。据我所知,push_back可以在C ++ 11中重载为:

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

这不会破坏向后兼容性,同时允许您传递N个参数,包括将调用正常rvalue或复制构造函数的参数。实际上,push_back()的GCC C ++ 11实现无论如何都只调用了emplace_back:

  void push_back(value_type&& __x)
  { 
    emplace_back(std::move(__x)); 
  }

所以,就我看来,我不需要emplace_back()。他们需要添加的只是push_back()的重载,它接受可变参数,并将参数转发给元素构造函数。

我错了吗?是否有理由在这里需要一个全新的功能?

2 个答案:

答案 0 :(得分:40)

如果T有明确的转换构造函数,emplace_backpush_back之间会有不同的行为。

struct X
{
    int val;
    X() :val() {}
    explicit X(int v) :val(v) {}
};

int main()
{
    std::vector<X> v;
    v.push_back(123);    // this fails
    v.emplace_back(123); // this is okay
}

进行您建议的更改意味着push_back在该实例中是合法的,我认为这不是理想的行为。我不知道这是不是这个原因,但这是我唯一可以想到的。

答案 1 :(得分:1)

这是另一个例子。

老实说,两者在语义上如此不同,他们的相似行为应被视为仅仅巧合(由于C ++具有“复制构造函数”的事实一种特殊的语法)。

你应该使用emplace_back,除非你想要 in-place-construction 语义。
你很少需要这样的东西。通常push_back是您真正需要的语言。

#include <vector>

struct X { X(struct Y const &); };
struct Y { Y(int const &); operator X(); };

int main()
{
    std::vector<X> v;
    v.   push_back(Y(123));  // Calls Y::operator X() and Y::Y(int const &)
    v.emplace_back(Y(123));  // Calls X::X(Y const &) and Y::Y(int const &)
}