In C++, std::forward and std::move are two tools designed to optimize object resource management and enable move semantics. Both were introduced in C++11 and later versions, primarily for resource transfer and perfect forwarding, though they serve different purposes and application scenarios.
std::move
std::move is used to convert an lvalue to an rvalue reference, enabling move semantics. Move semantics allow resources (such as dynamically allocated memory) to be transferred from one object to another, which is typically more efficient than copying objects.
Example:
Consider a simple String class:
cppclass String { public: char* data; String(const char* p) { size_t size = strlen(p) + 1; data = new char[size]; memcpy(data, p, size); } ~String() { delete[] data; } // Move constructor String(String&& other) noexcept : data(other.data) { other.data = nullptr; } // Deleted copy constructor String(const String& other) = delete; };
In this example, we can use std::move to convert a String object to an rvalue, allowing the move constructor to be used instead of the copy constructor (which is deleted here):
cppString a("Hello"); String b(std::move(a)); // Using move constructor
std::forward
std::forward is used for perfect forwarding, which is very useful in function templates. It preserves the value category (lvalue or rvalue) of arguments when passing them to other functions. std::forward is typically used in conjunction with universal references.
Example:
Consider a template function that forwards arguments to a constructor:
cpptemplate<typename T, typename Arg> T create(Arg&& arg) { return T(std::forward<Arg>(arg)); } class Widget { public: Widget(int&& n) { std::cout << "Rvalue overload, n=" << n << "\n"; } Widget(int& n) { std::cout << "Lvalue overload, n=" << n << "\n"; } }; int main() { int a = 1; auto w1 = create<Widget>(a); // Calls lvalue overload auto w2 = create<Widget>(2); // Calls rvalue overload }
In this example, the create function uses std::forward to preserve the value category of arg and pass it correctly to the Widget constructor.
Summary
In short, std::move is used to explicitly convert an lvalue to an rvalue reference for move semantics, while std::forward is used to preserve the value category of parameters in template programming for perfect forwarding. Both tools are essential for optimizing performance and resource management in modern C++ programming.