std::move
performs an unconditional cast to an rvalue, while std::forward
casts its argument to an rvalue only if that argument is bound to an rvalue.
Some facts:
- Neither
std::move
norstd::forward
do anything at runtime. - Move request on
const
objects are treated as copy requests.
std::move
To make things concrete, a very basic implementation of std::move
in C++11 looks like this:
|
|
Or, a more elegant implementation in C++14:
|
|
Basically, std::move
does nothing but cast its argument to an rvalue, and we might think it as rvalue_cast
. Usually we want move
operation on rvalues, so every time we see a move
over some parameter, we know we want to perform move operation over the resulting rvalue. However, not all rvalues are candidates for moving, especailly those annotated by const
- move requests on const
objects are silentlly transformed into copy operation.
std::forward
std::move
unconditionally casts its argument to an rvalue, while std::forward
conditionally do so: it casts to an rvalue only if its argument was initialized with an rvalue.
The most common scenario is a function template taking a universal reference parameter that is to be passed to another function:
|
|
|
|
In the code above, std::forward
is able to tell whether param
is initialized with an lvalue or an rvalue because that information is encoded in logAndProcess
’s template parameter T
, which is then passed to std::forward
, which is able to recover the encoded information. For details, refer to EMCpp item 28.
Comparison
Depending on the usecase scenario, we can tell when to use which:
std:move
typically sets up a movestd::forward
just passes - forwards- an object to another function in a way that retains its original lvalueness or rvalueness.