In C++, lvalue (left value) is an expression that refers to an object in memory which has a name and can be referenced (e.g., a variable). rvalue (right value) is a temporary value that does not have a name and is not an object in the traditional sense (e.g., the result of a + b, literals like 5).
Lvalue can have its address taken, while rvalue cannot (before rvalue references were introduced). For passing them to functions, there are:
void foo(const std::string& s); — accept both lvalue and rvalue.void bar(std::string& s); — accept only lvalue.void baz(std::string&& s); — accept only rvalue.Example:
void takeValue(std::string& s) { } // lvalue void takeRValue(std::string&& s) { } // rvalue std::string s = "hello"; takeValue(s); // OK, lvalue takeRValue(std::string("hi")); // OK, rvalue
Rvalue references are needed for efficient transfer of temporary objects, primarily for move semantics, to move resources instead of copying them.
What type of reference (lvalue or rvalue) does the expression
std::move(obj)yield? What category does the object itself become after applying std::move?
Answer:
std::move(obj) always returns an rvalue reference (T&&), but the object itself remains an lvalue; it just undergoes an explicit conversion. After this, one must handle the object very carefully (it may be in an undefined, but valid state).
Example:
std::string s = "data"; std::string d = std::move(s); // d takes the data from s, s is now empty
History
In a large project, one of the developers passed temporary objects through an lvalue reference T& (instead of T&& or const T&). This led to compilation errors and suboptimal copies — move semantics were not used, and performance dropped by 40%.
History
In the frontend engine, std::move was incorrectly applied to variables that were used again afterward. As a result, the variables were in a "destroyed" state, leading to crashes and rendering thread failures.
History
In the serialization library, a container of type std::vector<T> was passed to a function as an lvalue, but move was expected. Instead of moving, expensive copying of a large number of elements occurred, which significantly worsened serialization time on large arrays.