There are many similar questions here. All of them asks about usage of std::move
in return
in specific cases. But I want to know when std::move
should be (or shouldn't be) used in return
statement in general.
Here I found the following answer:
All return values are already moved or else optimized out, so there is no need to explicitly move with return values.
Compilers are allowed to automatically move the return value (to optimize out the copy), and even optimize out the move!
So I expected that std::move
must never be used in return statement, because in any case compiler will optimize that. But I decided to check this and written the following test code:
class A
{
public:
A() {}
A(const A & a) { std::cout << "A(const A &)" << std::endl; }
A( A && a) { std::cout << "A( A &&)" << std::endl; }
};
A func1(bool first)
{
A a1, a2;
return (first ? a1 : a2);
}
int main()
{
A a1(func1(true));
return 0;
}
And here is what I got:
A(const A &)
So compiler did not automatically move the value in return statement, and I had to moved it manually:
return std::move(first ? a1 : a2);
This returned:
A( A &&)
However when I rewrote my code in such way:
A func2(bool first)
{
A a1, a2;
if (first) return a1; else return a2;
}
int main()
{
A a2(func2(true));
return 0;
}
I found that automatic move is working:
A( A &&)
Next test:
A func3(A &&a)
{
return a;
}
int main()
{
A a3(func3(A()));
return 0;
}
Result:
A(const A &)
So here return std::move(a)
must be used.
My understating is next. Compiler automatically moves (or even use RVO) only local variables (and parameters passed by value (they are actually local variables too)). Rvalue references passed as parameters must be moved manually (it's probably because compiler doesn't know whether this external reference will be used anywhere later). Also compiler use move only in “pure” return statement (return var;
) and can’t move when returning expression which uses local variables (return <some expression using var>
, e.g. return somefunc(var);
).
So std::move
should not be used in pure "return local variable" statements (using std::move
in this case prevents Return Value Optimization). In all other cases std::move
should be used in return
.
Is my understanding right?