Why couldn't push_back be overloaded to do the job of emplace_back?
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.
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:
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:
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.
Am I wrong here? Is there some reason that an entirely new function was needed here?
If T has an explicit conversion constructor, there is different behavior between emplace_back
and 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.
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).
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.
#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 &)
}
精彩评论