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?
Unlike push_back , which relies on compiler optimizations to avoid copies, emplace_back uses perfect forwarding to send the arguments directly to the constructor to create an object in-place. It seems to me that emplace_back does everything push_back can do, but some of the time it will do it better (but never worse).
because emplace_back would construct the object immediately in the vector, while push_back , would first construct an anonymous object and then would copy it to the vector.
C++ Vector Library - emplace_back() Function The C++ function std::vector::emplace_back() inserts new element at the end of vector. Reallocation happens if there is need of more space. This method increases container size by one.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With