c++ std::move std::forward
What's the difference between std::move and std::forward
C++ Rvalue References Explained
Modern C++ Tutorial: C++11/14/17/20 On the Fly
std::move
Long story short: std::move is for turning anything into an rvalue(¹), for the purpose of making it look like a temporary (even if it isn't: std::move(non_temporary)), so that its resources can be stolen from it, i.e. moved from it (provided this is not prevented by a const attribute; yes, rvalues can be const, in which case you can't steal resources from them).
std::move(x) says Hi guys, be aware that who I'm giving this x to can use and break it apart as he likes, so you typically use it on rvalue references parameters, because you're sure they are bound to temporaries.
std::forward
Long story short: std::forward is for forwarding an argument from inside a function to another function while telling the latter function whether the former was called with a temporary.
std::forward
(if x is bound to an rvalue, i.e. a temporary) Hi Mr Function, I've received this parcel from another function who doesn't need it after you work with it, so please feel free to do whatever you like with it;
(if x is bound to an lvalue, i.e. a non-temporary) Hi Mr Function, I've received this parcel from another function who does need it after you work with it, so please don't break it.
So you typically use it on forwarding/universal references, because they can bind to both temporaries and non temporaries.
In other words, std::forward is for being able to turn this code
template<typename T>
void wrapper(T&& /* univ. ref.: it binds to lvalues as well as rvalues (temporaries)*/ t) {
// here `t` is an lvalue, so it doesn't know whether it is bound to a temporary;
// `T` encodes this missing info, but sadly we're not making `some_func` aware of it,
// therefore `some_func` will not be able to steal resources from `t` if `t`
// is bound to a temporary, because it has to leave lvalues intact
some_func(t);
}
into this
template<typename T>
void wrapper(T&& /* univ. ref.: it binds to lvalues as well as rvalues (temporaries)*/ t) {
// here `t` is an lvalue, so it doesn't know whether it is bound to a temporary;
// `T` encodes this missing info, and we do use it:
// `t` bound to lvalue => `T` is lvalue ref => `std::forward` forwards `t` as lvalue
// `t` bound to rvalue => `T` is non-ref => `std::forward` turns `t` into rvalue
some_func(std::forward<T>(t));
}