std::vector::emplace_back and std::move

In the second version, there is an advantage. Calling emplace_back will call the move constructor of std::string when std::move is used, which could save on a copy (so long as that string isn't stored in a SSO buffer). Note that this is essentially the same as push_back in this case.

std::move in the first version is unnecessary, as the string is already a prvalue.

std::move in the third version is irrelevant, as a string literal cannot be moved from.

The simplest and most efficient method is this:

bar.emplace_back("some_string");

That requires no unnecessary std::string constructions as the literal is perfect-forwarded to the constructor.


emplace_back calls to somehthing like

new (data+size) T(std::forward<Args>(args)...);

if args are basic - non - rvalue-referenced std::string, the expression will compile to

new (data+size) std::string(str); //str is lvalue - calls std::string::string(const string& rhs)

meaning the copy constructor will take place. but, if you use std::move on str, the code will compile to

new (data+size) std::string(str); //str is r-value reference, calls std::string::string(string&& rhs)

so move semantics takes place. this is a huge performance gain.
do note, that str is lvalue, it has a name, so in order to create r-value-reference from it, you must use std::move.

in the example

vec.emplace_back("some literal"); 

the code will compile to

new (data+size) std::string("literal"); //calls std::string::string(const char*);

so no temporaries.

the third example is nonsense. you cannot move literals.


The whole idea of emplace_back is to get rid of copying and moving operations. You just need to pass input parameters of std::string into emplace_back. A std::string object will be constructed inside emplace_back method.

bar.emplace_back("some_string");

If you already have a string, it makes sense to use std::move. A std::string object will be constructed inside emplace_back by moving data from str.

std::string str("some_string");
bar.emplace_back(std::move(str));