Consider the following:
#include
#define trace(name) std::cout << #name << \" (\" << this << \"), i = \" << i
When move semantics where added to C++ in C++11, decisions where made about where to automatically do move construction.
The general rule that was followed was that implicit move should occur when copy elision would be legal.
Copy elision is legal when you have an anonymous object that you are copying to another instance. The compiler can legally elide the copy, and treat the two objects as one, with a lifetime equal to the union of the two objects lifetime.
The other time that copy elision is legal is when you return a local variable from a function. This was known as NRVO (named return value optimization). This optimization in C++03 let you declare a return value, and it is constructed directly in the place where the return value goes. When you return retval;
, no copy happens.
This is basically impossible to do without inlining when you return multiple different objects at different spots in your function.
However, when move semantics where added, this place was the other spot where implicit move can occur. A return local_var;
in a function returning a variable the same type as local_var
can be elided, and failing that, you can implicitly move from local_var
into the return value.