std::string my_func(){
return std::string("...");
}
std::string
can be replaced by std::vector
or anything else. In general, how do I know rv was moved and not copied?
std::string my_func(){
return std::string("...");
}
std::string
can be replaced by std::vector
or anything else. In general, how do I know rv was moved and not copied?
According to cppreference,
In C++11, expressions that ... do not have identity and can be moved from are called prvalue ("pure rvalue") expressions.
A temporary object like the one you are returning (std::string("...")
) has no identity and can be moved from because the compiler can detect that its state will not be used before its lifetime ends. Thus, the compiler will prefer to move the object over copying it.
However, the temporary object will likely not get moved or copied at all because of return value optimization (RVO), a form of copy elision optimization that constructs the object in the storage that it would otherwise be moved to. So if you were to write std::string str = my_func();
, the code would likely be optimized to construct str
from "..."
in-place, rather than constructing a string inside my_func()
and then moving it out. RVO applies for any kind of object that is copyable and/or movable.
A move constructor takes a rvalue reference. A rvalue reference is preferred over a lvalue reference to const when dealing with prvalues. So, as long as your type has a valid move constructor the compiler will chose the move constructor and only fall back to the copy constructor if there isn't move constructor.
That said in this case most likely nothing will be copied or moved and RVO will kick in which directly constructs the object at the call site. The only way to know though if it did is to inspect the assembly.
Starting in C++17 with guaranteed copy elision you are actually guaranteed that no copy or move will happen here.