What are rvalues, lvalues, xvalues, glvalues, and prvalues?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
These C++ terms classify expressions by identity and lifetime. They matter because overload resolution, move semantics, references, and template behavior all depend on whether an expression names a stable object or a temporary value.
Start with lvalue and rvalue
Historically, the easiest model was simple: an lvalue refers to an object with identity, while an rvalue is a temporary value. Modern C++ refined that model, but it is still the best place to start.
If an expression has a persistent identity that you can generally take the address of, think lvalue. If it is a temporary computation result, think rvalue.
The Modern Categories
In current standard terminology, value categories are split more precisely:
- '
glvalue: an expression that identifies an object, bit-field, or function.' - '
lvalue: a kind ofglvaluethat is not expiring.' - '
xvalue: an "expiring value", still tied to an object identity, but eligible for resource reuse.' - '
prvalue: a "pure rvalue", typically a temporary value without stable identity in the older mental model.'
The umbrella term rvalue means either prvalue or xvalue.
The hierarchy is useful:
- '
glvalue=lvalueorxvalue' - '
rvalue=prvalueorxvalue'
That overlap is why xvalue matters. It has identity like a glvalue, but also behaves like an rvalue for move operations.
Why xvalue Exists
xvalue is the category most closely tied to move semantics. An object returned by std::move is not magically moved by itself; it becomes an xvalue expression, which allows overloads taking T&& to prefer moving from it.
std::move(name) still refers to the same object name, so it has identity. That is why it is an xvalue rather than a prvalue.
Why prvalue Exists
A prvalue is a pure computed value such as a literal or the result of arithmetic. In everyday practice, prvalues are what you think of as temporaries.
You do not usually care whether something is specifically a prvalue unless you are reasoning about overload resolution, copy elision, or template deduction.
Reference Binding Makes the Distinction Concrete
The easiest way to internalize the categories is to see what kinds of references can bind.
This is why the terminology matters: the compiler uses value categories to decide which operations are legal and which overload is best.
Common Pitfalls
- Treating
std::moveas an actual move instead of a cast to an xvalue expression. - Assuming every rvalue is a prvalue, which hides the role of xvalues.
- Overcomplicating everyday code when only the
lvalueversusrvaluedistinction is relevant. - Forgetting that named rvalue references are themselves lvalues once they have a name.
- Memorizing the category list without connecting it to reference binding and overload resolution.
Summary
- '
lvaluemeans an expression with stable identity, typically a named object.' - '
prvaluemeans a pure temporary value such as a literal or arithmetic result.' - '
xvaluemeans an expiring object expression, often produced bystd::move.' - '
glvaluegroupslvalueandxvalue, whilervaluegroupsprvalueandxvalue.' - The practical payoff is understanding move semantics, overload resolution, and reference binding.

