3

Does it still make sense in C++11 to use vector::push_back() instead of vector::emplace_back(), and similarly map::insert() instead of map::emplace()?

My understanding is that the new modern C++11 emplace-methods construct objects in place with the given arguments (perfectly forwarded to constructors), so they save copy and move operations, so they should be more efficient than their old C++98/03 counterparts.

Am I missing something about that?

Is it safe to discourage the use of the old-style methods?

Mr.C64
  • 41,637
  • 14
  • 86
  • 162
  • 1
    Sound about right? http://stackoverflow.com/questions/10890653/why-would-i-ever-use-push-back-instead-of-emplace-back – chris Apr 08 '14 at 13:31
  • If you need backwards compatibility? – RedX Apr 08 '14 at 13:32
  • emplace_back() will call constructors, push_back() will invoke copy or move for existing object. – berkus Apr 08 '14 at 13:34
  • @chris: According to the thread you linked (thanks), it seems that the only reason to use `vector::push_back` instead of `emplace_back` is being able to use uniform initialization. Is my understanding correct? Anyway, from a perf perspective, `emplace_back` should be better, right? – Mr.C64 Apr 08 '14 at 13:35
  • @RedX: If it's only for backwards compatibility, then can they be discouraged for new code? – Mr.C64 Apr 08 '14 at 13:36
  • @berkus: Do you mean: "if you already have an object created elsewhere, use push_back; else, if you are creating the object just to put it into vector, use emplace_back"? Thanks. – Mr.C64 Apr 08 '14 at 13:37
  • BTW: If you guys write your notes as answers instead of comments, I'd be happy to give proper credit upvoting them. – Mr.C64 Apr 08 '14 at 13:39
  • Yes, pretty much. The signature of push_back accepts either a const reference or refref to your already existing object. emplace_back accepts only arguments to the constructor for given type. – berkus Apr 08 '14 at 13:41

2 Answers2

2

From the difference in signatures of push_back() and emplace_back() it's easy to see that push_back will work with already made object (a temporary if you create it at the call site or implicitly), while emplace_back() will construct an object from passed arguments in place using perfect forwarding.

void push_back( const T& value );
void push_back( T&& value );

vs

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

Code sample

vector<int> v;
v.push_back(1); // "Constructs" an int object in place, then passes it by reference or refref
v.emplace_back(1); // Calls int constructor with argument 1 directly in place in vector


vector<SpaceShip> u;
u.push_back(SpaceShip(new Engine(), new Hull())); // Make a temporary, then COPY or MOVE
u.emplace_back(new Engine(), new Hull()); // Construct in place
berkus
  • 1,552
  • 12
  • 16
  • I'd consider differences for objects bigger and more complex than simple integers :) – Mr.C64 Apr 08 '14 at 13:45
  • Well, int is just an example. Of course a complex object would have more overhead and be more interesting. – berkus Apr 08 '14 at 13:46
1

As you say, emplace_back is meant to construct objects. So what if you already have an object and you want to copy or move it inside the container? Why should you call emplace_back to create a new instance, even if you can move your existing object into this new instance?

Both alternatives can be useful, for different purposes. emplace_back might be able to do exactly the same with push_back with the same performance, but it's still cleaner to show your intent in your code.

iavr
  • 7,547
  • 1
  • 18
  • 53