c++move-semanticsnrvo

Can NRVO and Move Semantics Be Used Together in C++?


I'm reading about move semantics in C++ from the book C++ Move Semantics. The book assumes NRVO is used in the createAndInsert() function's return statement. However, it also states that move semantics are applied when v = createAndInsert(); is executed in main().

My question is: If NRVO is already applied, shouldn't coll be constructed directly in the space for v, thus making any move operations unnecessary in main()? Could this be for learning purposes in the book, or is it suggesting what happens if NRVO were not applied, despite stating it is? I'm trying to understand if I'm missing something about how NRVO and move semantics interact in this scenario.

Thanks for your insights!

#include <string>
#include <vector>

std::vector<std::string> createAndInsert()
{
    std::vector<std::string> coll;  // create vector of strings
    coll.reserve(3);                // reserve memory for 3 elements
    std::string s = "data";         // create string object

    coll.push_back(s);              // insert string object
    coll.push_back(s+s);            // insert temporary string
    coll.push_back(std::move(s));   // insert string (we no longer need the value of s)

    return coll;                    // return vector of strings
}

int main()
{
    std::vector<std::string> v;     // create empty vector of strings
    //...
    v = createAndInsert();          // assign returned vector of strings
    //...
}

Solution

  • If you were to do std::vector<std::string> v = createAndInsert();, first there would be a move from coll to the returned temporary (NRVO may or may not elide it), then another move from that temporary to v (this is always elided since C++17).

    But when doing std::vector<std::string> v; v = createAndInsert();, the second move can never be elided, because the object is already constructed.