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
//...
}
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.