I read many answer that local variable can be safely returned by std::move
.
But when I tried it, compiler shows warning like below.
class MyClass {};
MyClass&& func() {
MyClass c;
return std::move(c);
}
int main() {
func();
}
warning: reference to stack memory associated with local variable 'c' returned [-Wreturn-stack-address]
return std::move(c);
^
What is wrong with above code?
In your code sample, you return a (rvalue-)reference to a local variable. Since the local variable is destroyed after the function call is completed, using such returned value is Undefined Behaviour.
On the other hand, if you return by value instead (which you should), using std::move
is probably not a good idea.
Indeed, due to NRVO (Named Return Value Optimization), the compiler is allowed to perform copy elision in order to avoid an unnecessary copy/move.
Actually, NRVO is not mandatory so the move constructor may be called (but in practice, it won't happen since most compiler will perform the optimization).
Knowing that, if you explicitly use std::move
, since the move constructor may have side effect, you make your variable not eligible for NRVO, which translates the above "move constructor may be called" into "move constructor will be called", which is a pessimization.
Thus, except if you definitely want to call the move constructor (e.g. for a specific behavior implemented inside), you should not return with std::move
.
In other words, if it's only a performance concern, the compiler will do it better than you with copy elision.
Consequently, the right version would be:
MyClass func() // Return by value
{
MyClass c;
/*
Do whatever you want with c.
*/
return c; // NRVO (copy elision)
}