C++ Programming
Programming Concepts
Rvalue and Lvalue
Programming Terminology
Advanced Coding

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.

cpp
1#include <iostream>
2#include <string>
3
4int main() {
5    int x = 10;        // x is an lvalue expression
6    int y = x + 1;     // x + 1 is an rvalue expression
7
8    int& ref = x;      // binds to lvalue
9    // int& bad = 5;   // error: non-const lvalue reference cannot bind to rvalue
10
11    const int& ok = 5; // const lvalue reference can bind to rvalue
12    std::cout << ref << " " << ok << "\n";
13}

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 of glvalue that 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 = lvalue or xvalue'
  • 'rvalue = prvalue or xvalue'

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.

cpp
1#include <iostream>
2#include <string>
3#include <utility>
4
5void log(const std::string& s) {
6    std::cout << "lvalue overload: " << s << "\n";
7}
8
9void log(std::string&& s) {
10    std::cout << "rvalue overload: " << s << "\n";
11}
12
13int main() {
14    std::string name = "codemia";
15    log(name);              // lvalue
16    log(std::move(name));   // xvalue, calls rvalue overload
17    log(std::string("tmp")); // prvalue, also calls rvalue overload
18}

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.

cpp
1int make_number() {
2    return 42; // prvalue
3}
4
5int main() {
6    int a = make_number();
7    int b = 1 + 2;
8}

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.

cpp
1int main() {
2    int x = 7;
3
4    int& lref = x;          // lvalue reference binds to lvalue
5    const int& cref = 9;    // const lvalue reference binds to prvalue
6    int&& rref = 9;         // rvalue reference binds to prvalue
7    int&& moved = std::move(x); // binds to xvalue
8}

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::move as 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 lvalue versus rvalue distinction 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

  • 'lvalue means an expression with stable identity, typically a named object.'
  • 'prvalue means a pure temporary value such as a literal or arithmetic result.'
  • 'xvalue means an expiring object expression, often produced by std::move.'
  • 'glvalue groups lvalue and xvalue, while rvalue groups prvalue and xvalue.'
  • The practical payoff is understanding move semantics, overload resolution, and reference binding.

Course illustration
Course illustration

All Rights Reserved.