1146

I'm a bit confused regarding the difference between push_back and emplace_back.

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

As there is a push_back overload taking a rvalue reference I don't quite see what the purpose of emplace_back becomes?

Ajay
  • 18,086
  • 12
  • 59
  • 105
ronag
  • 49,529
  • 25
  • 126
  • 221
  • 13
    Some good reading here: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2642.pdf – Johan Kotlinski Nov 29 '10 at 14:00
  • 19
    Note that (as Thomas says below), the code in the question is from MSVS's *emulation* of C++0x, not what C++0x actually is. – me22 Dec 21 '10 at 05:50
  • 5
    A better paper to read would be: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2345.pdf. N2642 is mostly wording for the Standard; N2345 is the paper that explains and motivates the idea. – Alan Mar 13 '13 at 23:10
  • Note that even in MSVC10 there is a `template void emplace_back(_Valty&& _Val)` version that takes a [universal reference](https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers) which provides perfect forwarding to `explicit` single argument constructors. – joki Jul 11 '17 at 19:10
  • Related: Is there any case where `push_back` is preferable to `emplace_back`? The only case I can think of is if a class were somehow copyable (`T&operator=(constT&)`) but not construct-able (`T(constT&)`), but I can't think of why one would ever want that. – Ben May 25 '18 at 18:44
  • Also see [this](https://stackoverflow.com/questions/10890653/why-would-i-ever-use-push-back-instead-of-emplace-back). – Albert Oct 23 '18 at 21:50
  • @Ben Everyone else (if I may presume) interprets an unqualified "copyable" to mean copy-constructible, not copy-assignable as you showed. Both `emplace_back()` and `push_back()` will invoke the copy-constructor - i.e. both perform construction, i.e. neither perform assignment - so your suggested class would not fare any better with either. – underscore_d Jan 06 '19 at 15:09
  • The related case I tripped over (that I mentioned just now in a separate thread on this page) is that `emplace_back` will "implicitly" call `explicit` constructors, which could lead to undesired behavior. (For heavy classes, I often make the copy c'tor `explicit` leaving the move-c'tor implicit. `v.emplace_back(x)` bit me by doing basically `v.emplace_back(X(x))` when I hoped it to error and force me to write `v.push_back(std::move(x))`.) – Ben Oct 25 '19 at 19:22
  • *Excellent* and easy-to-understand answer here: https://www.quora.com/In-what-scenarios-should-I-use-emplace_back-instead-of-push_back-in-C%2B%2B/answer/Kevin-Mather?ch=10&share=46e9e37c&srid=CWXc – Gabriel Staples Nov 13 '19 at 21:18
  • Related: [Why would I ever use push_back instead of emplace_back?](https://stackoverflow.com/questions/10890653/why-would-i-ever-use-push-back-instead-of-emplace-back/10890716) – Gabriel Staples Nov 10 '20 at 23:15
  • two series of articles on this topic : https://medium.com/@its.me.siddh/modern-c-series-vector-push-back-or-emplace-back-e3a482ab4dcd https://medium.com/@its.me.siddh/modern-c-series-vector-push-back-or-emplace-back-part2-1ad564a5711b – kfc Mar 19 '23 at 19:08

7 Answers7

807

In addition to what visitor said :

The function void emplace_back(Type&& _Val) provided by MSCV10 is non-conforming and redundant because as you noted it is strictly equivalent to push_back(Type&& _Val).

But the real C++0x form of emplace_back is really useful: void emplace_back(Args&&...);

Instead of taking a value_type, it takes a variadic list of arguments, so that means that you can now perfectly forward the arguments and construct directly an object into a container without a temporary at all.

That's useful because no matter how much cleverness RVO and move semantics bring to the table, there are still complicated cases where a push_back is likely to make unnecessary copies (or move). For example, with the traditional insert() function of a std::map, you have to create a temporary, which will then be copied into a std::pair<Key, Value>, which will then be copied into the map :

std::map<int, Complicated> m;
int anInt = 4;
double aDouble = 5.0;
std::string aString = "C++";
    
// cross your finger so that the optimizer is really good
m.insert(std::make_pair(4, Complicated(anInt, aDouble, aString))); 

// should be easier for the optimizer
m.emplace(4, anInt, aDouble, aString);

So why didn't they implement the right version of emplace_back in MSVC? Actually, it bugged me too a while ago, so I asked the same question on the Visual C++ blog. Here is the answer from Stephan T Lavavej, the official maintainer of the Visual C++ standard library implementation at Microsoft.

Q: Are beta 2 emplace functions just some kind of placeholder right now?

A: As you may know, variadic templates aren't implemented in VC10. We simulate them with preprocessor machinery for things like make_shared<T>(), tuple, and the new things in <functional>. This preprocessor machinery is relatively difficult to use and maintain. Also, it significantly affects compilation speed, as we have to repeatedly include subheaders. Due to a combination of our time constraints and compilation speed concerns, we haven't simulated variadic templates in our emplace functions.

When variadic templates are implemented in the compiler, you can expect that we'll take advantage of them in the libraries, including in our emplace functions. We take conformance very seriously, but unfortunately, we can't do everything all at once.

It's an understandable decision. Everyone who tried just once to emulate variadic template with preprocessor horrible tricks knows how disgusting this stuff gets.

Milan
  • 1,743
  • 2
  • 13
  • 36
Arzar
  • 13,657
  • 3
  • 25
  • 25
  • 154
    That clarification that it's a MSVS10 issue, not a C++ issue is the most important part here. Thanks. – me22 Dec 21 '10 at 05:49
  • 12
    I believe your last line of C++ code won't work. `pair` does not have a constructor that takes an int, another int, a double and as 4th parameter a string. However, you *can* directly construct this pair object using its piecewise-constructor. The syntax will be different, of course: `m.emplace(std::piecewise,std::forward_as_tuple(4),std::forward_as_tuple(anInt,aDouble,aString));` – sellibitze Mar 14 '13 at 15:08
  • 4
    Happily variadic templates will be in VS2013, now in preview. – Daniel Earwicker Jul 25 '13 at 20:37
  • 13
    should this answer be updated to reflect the new developments in vs2013? – a06e Feb 27 '14 at 16:20
  • sorry, but -1 for what @sellibitze said; it was the same compilation error that brought me here looking for help, but all we get is a false statement that the quoted syntax will work (it doesn't). the rest of the text is merely ok. with these 2 things, i dunno why this got upvoted so far. – underscore_d Dec 06 '15 at 23:50
  • 8
    If you're using Visual Studio 2013 or later _now_, you should have support for the "real" `emplace_back` so long as it was implemented into Visual C++ when variadic templates were added: https://msdn.microsoft.com/en-us/library/hh567368.aspx – kayleeFrye_onDeck Jun 28 '17 at 20:17
  • 1
    @sellibitze but then you made a mistake while correcting Thomas's mistake... There is no `std::piecewise`; there are only the type `std::piecewise_construct_t` and the global instance thereof `std::piecewise_construct`. – underscore_d Jan 06 '19 at 14:14
  • 1
    with gcc 9.2 m.emplace(4, Complicated(anInt, aDouble, aString)) ; works. – kalyanswaroop Mar 02 '20 at 16:14
  • @ThomasPetit , what is this MSCV10 – juztcode Jun 29 '20 at 11:51
  • I think Thomas meant to write, MSVC10 = MicroSoft Visual C++ 10. – unrealsoul007 Jul 15 '21 at 00:05
263

emplace_back shouldn't take an argument of type vector::value_type, but instead variadic arguments that are forwarded to the constructor of the appended item.

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

It is possible to pass a value_type which will be forwarded to the copy constructor.

Because it forwards the arguments, this means that if you don't have rvalue, this still means that the container will store a "copied" copy, not a moved copy.

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

But the above should be identical to what push_back does. It is probably rather meant for use cases like:

 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
visitor
  • 8,564
  • 2
  • 26
  • 15
  • You would need to use vec.emplace_back(std::move(s)); since s is an lvalue to get the move behavior – David Nov 29 '10 at 12:57
  • 2
    @David: but then you have a moved `s` in scope, isn't that dangerous ? – Matthieu M. Nov 29 '10 at 17:56
  • 3
    It's not dangerous if you don't plan on using s any longer for its value. Moving does not make s invalid, the move will only steal the internal memory allocation already done in s and leave it in a defaulted state (no sting allocated) which when destructed will be fine as if you had just typed std::string str; – David Nov 30 '10 at 00:52
  • 4
    @David: I'm not sure that a moved-from object is required to be valid for any use except subsequent destruction. – Ben Voigt Dec 12 '10 at 01:31
  • 65
    `vec.emplace_back("Hello")` will work, since the `const char*` argument will be *forwarded* to the `string` constructor. This is the whole point of `emplace_back`. – Alexandre C. Aug 09 '11 at 20:28
  • visitor, you are dead wrong, please read Alexandre C. comment and Thomas answer – lurscher Jan 17 '12 at 16:28
  • `vec.emplace_back(std::string("Hello"))` will also prevent the default string constructor from being called. – DRayX Feb 06 '12 at 23:19
  • 9
    @BenVoigt: A moved-from object is required to be in a valid (but unspecified) state. This doesn't necessarily mean you can perform any operation on it, however. Consider `std::vector`. An empty `std::vector` is a valid state, but you cannot call `front()` on it. This means that any function that has no preconditions can still be called (and destructors can never have preconditions). – David Stone May 10 '12 at 04:06
  • why spend 2/3rds of the answer dwelling on the extremely mundane 'emplace is bad for use-cases that aren't the ones for which it was designed', relegating the actual rationale to a "probably" afterthought? – underscore_d Dec 06 '15 at 23:53
145

Optimization for emplace_back can be demonstrated in following example.

For emplace_back, constructor A (int x_arg) will be called.

For push_back, A (int x_arg) is called first and move A (A &&rhs) is called afterward.

Of course, the constructor has to be marked as explicit, but for the current example, it is good to remove explicitness.

#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;
}

output:

call emplace_back:
A (x_arg)

call push_back:
A (x_arg)
A (A &&)
Milan
  • 1,743
  • 2
  • 13
  • 36
vadikrobot
  • 1,725
  • 1
  • 10
  • 8
  • I came here after noticing that I had code that was calling `v.emplace_back(x);` where x is explicitly move-constructable but only explicitly copy-constructable. The fact that `emplace_back` is "implicitly" explicit makes me think that my go-to function for appending should probably be `push_back`. Thoughts? – Ben Oct 25 '19 at 19:19
  • If you call `a.emplace_back` second time, the move constructor will be called! – Andreas K. May 21 '20 at 15:18
  • 2
    @AndreasK. That's not related to emplace_back but rather expanding the size of the vector. You can check that by printing what is being moved rather than just `"A (A &&)\n"`, print `"A (A &&) on " << rhs.x << "\n"`. You can see it [in this edited code snippet](https://www.mycompiler.io/view/FSiSqRh). – Brambor Aug 25 '21 at 22:09
26

Specific use case for emplace_back: If you need to create a temporary object which will then be pushed into a container, use emplace_back instead of push_back. It will create the object in-place within the container.

Notes:

  1. push_back in the above case will create a temporary object and move it into the container. However, in-place construction used for emplace_back would be more performant than constructing and then moving the object (which generally involves some copying).
  2. In general, you can use emplace_back instead of push_back in all the cases without much issue. (See exceptions)
vaibhav kumar
  • 885
  • 1
  • 11
  • 13
25

One more example for lists:

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

// creates a new object and then copies (or moves) that object.
push_back(ExplicitDataType{"element"});
Olivia Stork
  • 4,660
  • 5
  • 27
  • 40
  • 5
    does it mean emplace_back does not create a copy ? It just stores the actual object. if we change the object itself after emplace_back , the object in vector should also change ,right? – Mr Nobody Dec 20 '20 at 07:32
  • @MrNobody with `emplace_back` it is the container that forwards the arguments to the constructor - aka neither before nor after that call do you have any object at hand. what do you mean by "change the object itself"? There is ONLY the object in the container. Or you create the object beforehand - in which case it acts the same as push_back. – ABaumstumpf Feb 14 '22 at 13:46
  • @MrNobody In order to see the effect you mention, the object that is emplace_back'd into the vector has to have an identity, in which case the object would have been copied rather than being directly inserted into the vector. See visitor's example. – ConventionalProgrammer May 03 '23 at 08:05
12

A nice code for the push_back and emplace_back is shown here.

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

You can see the move operation on push_back and not on emplace_back.

Dharma
  • 2,425
  • 3
  • 26
  • 40
9

emplace_back conforming implementation will forward arguments to the vector<Object>::value_typeconstructor when added to the vector. I recall Visual Studio didn't support variadic templates, but with variadic templates will be supported in Visual Studio 2013 RC, so I guess a conforming signature will be added.

With emplace_back, if you forward the arguments directly to vector<Object>::value_type constructor, you don't need a type to be movable or copyable for emplace_back function, strictly speaking. In the vector<NonCopyableNonMovableObject> case, this is not useful, since vector<Object>::value_type needs a copyable or movable type to grow.

But note that this could be useful for std::map<Key, NonCopyableNonMovableObject>, since once you allocate an entry in the map, it doesn't need to be moved or copied ever anymore, unlike with vector, meaning that you can use std::map effectively with a mapped type that is neither copyable nor movable.

Germán Diago
  • 7,473
  • 1
  • 36
  • 59