In the case of return std::move(foo);
the move
is superfluous because of 12.8/32:
When the criteria for elision of a copy operation are met or would be
met save for the fact that the source object is a function parameter,
and the object to be copied is designated by an lvalue, overload
resolution to select the constructor for the copy is ?rst performed as
if the object were designated by an rvalue.
return foo;
is a case of NRVO, so copy elision is permitted. foo
is an lvalue. So the constructor selected for the "copy" from foo
to the return value of meh
is required to be the move constructor if one exists.
Adding move
does have a potential effect, though: it prevents the move being elided, because return std::move(foo);
is not eligible for NRVO.
As far as I know, 12.8/32 lays out the only conditions under which a copy from an lvalue can be replaced by a move. The compiler is not permitted in general to detect that an lvalue is unused after the copy (using DFA, say), and make the change on its own initiative. I'm assuming here that there's an observable difference between the two -- if the observable behavior is the same then the "as-if" rule applies.
So, to answer the question in the title, use std::move
on a return value when you want it to be moved and it would not get moved anyway. That is:
- you want it to be moved, and
- it is an lvalue, and
- it is not eligible for copy elision, and
- it is not the name of a by-value function parameter.
Considering that this is quite fiddly and moves are usually cheap, you might like to say that in non-template code you can simplify this a bit. Use std::move
when:
- you want it to be moved, and
- it is an lvalue, and
- you can't be bothered worrying about it.
By following the simplified rules you sacrifice some move elision. For types like std::vector
that are cheap to move you'll probably never notice (and if you do notice you can optimize). For types like std::array
that are expensive to move, or for templates where you have no idea whether moves are cheap or not, you're more likely to be bothered worrying about it.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…