C ++ 11 efficiency push_back () with std :: move versus emplace_back () for already built objects

In C ++ 11, emplace_back() usually preferable (in terms of efficiency) to push_back() , since it allows you to build in place , but does this still occur when using push_back(std::move()) constructed object?

For example, emplace_back() is still preferable in the following cases:

 std::string mystring("hello world"); std::vector<std::string> myvector; myvector.emplace_back(mystring); myvector.push_back(std::move(mystring)); // (of course assuming we don't care about using the value of mystring after) 

Also, is there an advantage in the above example instead:

 myvector.emplace_back(std::move(mystring)); 

or is this movement completely redundant or has no effect?

+61
c ++ 11 move-semantics push-back emplace
Nov 11 '14 at 8:41
source share
2 answers

See what various challenges you provided:

  • emplace_back(mystring) : This is the inline construction of a new element with any argument that you provide. Since you provided an lvalue, this in-place build is actually a copy, i.e. This is the same as calling push_back(mystring)

  • push_back(std::move(mystring)) : This causes a move-insert, which in the case of std :: string ist-in-place move-construction.

  • emplace_back(std::move(mystring)) : This is again a construction in place with the arguments you provided. Since this argument is an rvalue value, it calls the constructor move std::string , i.e. This is a layout for moving in place, as in 2.

In other words, if called with a single argument of type T, whether rvalue or lvalue, emplace_back and push_back equivalent.

However, for any other argument (s), emplace_back wins the race, for example, with char const* in vector<string> :

  1. emplace_back("foo") calls string::string(char const*) for the inline construct.

  2. push_back("foo") first needs to call string::string(char const*) to implicitly convert it to match the signature of the function, and then insert with the move, similar to case 2. above. Therefore, it is equivalent to push_back(string("foo"))

+79
Nov 11 '14 at 9:27
source share

emplace_back gets the list of rvalue links and tries to create a container element right in place. You can call emplace_back with all types supported by container element constructors. When you call emplace_back for parameters that are not rvalue links, they "return" to normal links and at least the copy constructor is called when the parameter and container elements are of the same type. In your case, "myvector.emplace_back (mystring)" should make a copy of the string because the compiler could not know that the myvector parameter is movable. So insert std :: move, which gives you the desired advantage. Push_back should work in the same way as emplace_back for already constructed elements.

+1
Nov 11 '14 at 9:55
source share



All Articles