Table of Contents

C++ Value categories

Value categories classify expressions based on whether they can be used to obtain an object's address and whether they're about to be destroyed. Lvalues have persistent identity and can be referenced; rvalues (temporaries or results of std::move) are about to disappear. This distinction enables move semantics and perfect forwarding.

Understand value categories to predict which overloads are chosen and how move semantics behave.

Example

This example shows how value categories determine which constructor or assignment operator is called.

// compile: g++ -std=c++17 -o values values.cpp
// run: ./values
// description: value categories determine move vs copy semantics
 
#include <iostream>
 
class Widget {
public:
    Widget() { std::cout << "Default\n"; }
    Widget(const Widget&) { std::cout << "Copy\n"; }
    Widget(Widget&&) { std::cout << "Move\n"; }
};
 
int main() {
    Widget a;              // lvalue: default constructor
    Widget b = a;          // lvalue: copy
    Widget c = Widget();   // rvalue: move (or elision)
 
    Widget d = std::move(a);  // move: cast lvalue to rvalue
 
    return 0;
}