c++stringc++11vector

push_back vs emplace_back to a std::vector<std::string>


Similar questions exist here and here but I think we haven't got a clear answer.

The C++11 standard has two ways to add a new element to the end of a vector: std::vector::push_back and std::vector::emplace_back.

The difference between them is the std::vector::emplace_back constructs the object in place and std::vector::push_back basically copies the object (or primitive type) or moves it to the end of vector.

Then, std::vector::push_back looks like the better option to add primitive types into a std::vector. For example:

std::vector<int> vVec;
vVec.push_back(10);
int iVar = 30;
vVec.push_back(iVar);

But it is not so clear to me when we talk about non-primitive types. Let's take a vector of std::string for example. If I want to add a literal string I shall use std::vector::emplace_back and when I want to copy or move a string object I shall use std::vector::push_back?

To make it clearer what I'm asking, let's see a few scenarios:

1st scenario:

std::vector<string> vVec;
std::string sTest("1st scenario");
vVec.push_back(sTest);  
vVec.emplace_back(sTest); 

push_back makes a copy of sTest as a new element at the end of vVec meanwhile emplace_back creates the string object an the end of vVec and copies the content of sTest into it. Which one is more efficient in this case? Or doesn't it matter?

2nd scenario:

std::vector<string> vVec;
std::string sTest1("2st scenario");
std::string sTest2("2st scenario");
vVec.push_back(move(sTest1));   
vVec.emplace_back(move(sTest2)); 

push_back is ready for move semantics, but what happens with emplace_back? Which one is more efficient in this case?

3rd scenario:

std::vector<string> vVec;
std::string sTest("3st scenario");
vVec.push_back(sTest.substr(4,4));
vVec.emplace_back(sTest.substr(4,4));

Because std::string::substr returns another std::string we have the same situation as in the 2nd scenario?

Conclusion

If std::vector::emplace_back is more efficient than std::vector::push_back only when literals are involved (in place construction), is its use really justified? If it is, can you give me some examples?

Important to note that std::vector::emplace_back was implemented in C++11 not in C++0x then I suppose there is a good reason for it to exists.


Solution

  • I take a while to really understand what the advantage to use std::vector::emplace as aschepler said.

    I found out the better scenario to use that is when we have our own class that receive some data when it is construct.

    To make more clear, let's suppose we have:

    1. A vector of MyObject
    2. MyObject needs to receive 3 arguments to be constructed
    3. The functions get1stElem(), get2ndElem() and get3rdElem() provide the elements necessary to construct a MyObject instance

    Then we can have a line like this:

    vVec.emplace(get1stElem(), get2ndElem(), get3rdElem());
    

    Then the std::vector::emplace will construct MyObject in place more efficiently than std::vector::push_back.