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

时间:2021-06-28 04:14:50

Firstly, I'm aware of this question, but I don't believe I'm asking the same thing.

首先,我知道这个问题,但我不相信我在问同样的问题。

I know what std::vector<T>::emplace_back does - and I understand why I would use it over push_back(). It uses variadic templates allowing me to forward multiple arguments to the constructor of a new element.

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

But what I don't understand is why the C++ standard committee decided there was a need for a new member function. Why couldn't they simply extend the functionality of push_back(). As far as I can see, push_back could be overloaded in C++11 to be:

但我不明白的是,为什么c++标准委员会决定需要一个新的成员函数。为什么不能简单地扩展push_back()的功能呢?在我看来,push_back在c++ 11中可以被重载为:

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

This would not break backwards compatibility, while allowing you to pass N arguments, including arguments that would invoke a normal rvalue or copy constructor. In fact, the GCC C++11 implementation of push_back() simply calls emplace_back anyway:

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

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

So, the way I see it, there is no need for emplace_back(). All they needed to add was an overload for push_back() which accepts variadic arguments, and forwards the arguments to the element constructor.

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

Am I wrong here? Is there some reason that an entirely new function was needed here?

我错了吗?这里是否需要一个全新的函数?

2 个解决方案

#1


38  

If T has an explicit conversion constructor, there is different behavior between emplace_back and push_back.

如果T有一个显式的转换构造函数,则emplace_back和push_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
}

Making the change you suggest would mean that push_back would be legal in that instance, and I suppose that was not desired behavior. I don't know if this is the reason, but it's the only thing I can come up with.

做出您建议的更改将意味着push_back在这种情况下是合法的,我认为这不是期望的行为。我不知道这是否是原因,但这是我唯一能想到的。

#2


1  

Here's another example.

这是另一个例子。

Honestly, the two are semantically so different, that their similar behavior should be regarded as a mere coincidence (due to the fact that C++ has "copy constructors" with a particular syntax).

老实说,这两者在语义上是如此的不同,以至于它们相似的行为应该被视为纯粹的巧合(因为c++有具有特定语法的“复制构造函数”)。

You should really not use emplace_back unless you want in-place-construction semantics.
It's rare that you'd need such a thing. Generally push_back is what you really, semantically want.

除非需要位置构造语义,否则不应该使用emplace_back。你很少需要这样的东西。通常,从语义上讲,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 &)
}

#1


38  

If T has an explicit conversion constructor, there is different behavior between emplace_back and push_back.

如果T有一个显式的转换构造函数,则emplace_back和push_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
}

Making the change you suggest would mean that push_back would be legal in that instance, and I suppose that was not desired behavior. I don't know if this is the reason, but it's the only thing I can come up with.

做出您建议的更改将意味着push_back在这种情况下是合法的,我认为这不是期望的行为。我不知道这是否是原因,但这是我唯一能想到的。

#2


1  

Here's another example.

这是另一个例子。

Honestly, the two are semantically so different, that their similar behavior should be regarded as a mere coincidence (due to the fact that C++ has "copy constructors" with a particular syntax).

老实说,这两者在语义上是如此的不同,以至于它们相似的行为应该被视为纯粹的巧合(因为c++有具有特定语法的“复制构造函数”)。

You should really not use emplace_back unless you want in-place-construction semantics.
It's rare that you'd need such a thing. Generally push_back is what you really, semantically want.

除非需要位置构造语义,否则不应该使用emplace_back。你很少需要这样的东西。通常,从语义上讲,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 &)
}