Loading lessons...
Value Categories: Lvalues and Rvalues
Value Categories: Lvalues and Rvalues
Every expression in C++ is either an lvalue or an rvalue. The historic terms mean "left value" and "right value", but the real test is the address.
Lvalue: a home in memory
An lvalue is an expression that refers to an object, something that lives at a memory address. A named variable is the classic example:
#include <iostream>
using namespace std;
int x = 5;
x = 10; // we can assign to it (it has an address)
int* p = &x; // we can take its address
Because x sits in memory, it has an identity and can be the topic of an assignment.
rvalue: a temporary
An rvalue is a temporary that is used for its value only - it has no persistent address:
5; // a literal number
x + 1; // the result of the calculation
There is no &5 - the value appears, is used, and evaporates.
A plain reference needs an lvalue
int& ref1 = x; // ok: x is an lvalue with an address
int& ref2 = 5; // error: 5 has no address to bind
An int& must bind to an lvalue. A temporary won't do.
const reference can bind to temporaries
const int& ref = 5; // ok! temporary lives as long as const&
A const int& is allowed to bind to an rvalue, because the compiler keeps the temporary alive for the lifetime of the reference - which is why functions accept literals with a const T&:
void printValue(const int& v) {
cout << v << endl;
}
printValue(7); // fine
TL;DR
- An lvalue is a value with a memory address (a variable).
- An rvalue is a temporary value with no persistent address.
int&binds only to lvalues.const int&can bind to temporaries too.