std::move: cast vô điều kiện một giá trị thành rvalue reference — cho phép move constructor/assignment "cướp" tài nguyên.
std::forward: cast có điều kiện — giữ nguyên value category (lvalue giữ lvalue, rvalue giữ rvalue) khi truyền tiếp vào hàm khác. Chỉ dùng với template forwarding reference (T&&).
Perfect forwarding pattern:
template <typename T>
void wrapper(T&& arg) {
// std::move(arg): luôn rvalue — có thể sai nếu arg là lvalue
// std::forward<T>(arg): đúng trong mọi trường hợp
doWork(std::forward<T>(arg));
}
std::string s = "hello";
wrapper(s); // arg là lvalue → forward giữ lvalue
wrapper(std::string{"world"}); // arg là rvalue → forward giữ rvalueQuy tắc:
- Dùng std::move khi bạn chắc chắn muốn move (biến local cuối cùng được dùng).
- Dùng std::forward trong template wrapper để không mất value category.
- Không dùng std::move trên function return value — RVO/NRVO hiệu quả hơn.
std::move: unconditionally casts a value to an rvalue reference — enabling a move constructor/assignment to "steal" its resources.
std::forward: conditionally casts — preserves the original value category (lvalue stays lvalue, rvalue stays rvalue) when passing an argument onward. Used only with template forwarding references (T&&).
Perfect forwarding pattern:
template <typename T>
void wrapper(T&& arg) {
// std::move(arg): always rvalue — wrong if arg is lvalue
// std::forward<T>(arg): correct in all cases
doWork(std::forward<T>(arg));
}
std::string s = "hello";
wrapper(s); // arg is lvalue → forward preserves lvalue
wrapper(std::string{"world"}); // arg is rvalue → forward preserves rvalueRules:
- Use std::move when you intentionally want to transfer ownership (last use of a local variable).
- Use std::forward in template wrappers to avoid losing value category.
- Don't std::move a return value — RVO/NRVO is more efficient.