Value Categories in C++


This post and the examples are from the Microsoft C++ Documentation.

Value Categories

Every C++ expression has a type and belongs to a value category. The value categories are the basis for rules that compilers must follow when creating, copying, and moving temporary objects during expression evaluation.

The C++ 17 standard defines expression value categories as follows:

  • A glvalue is an expression whose evaluation determines the identity of an object, bit-field, or function.

  • A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears. It has no address that is accessible by the program. Examples include literals, function calls that return a non-reference type, and temporary objects that are created during expression evaluation but accessible only by the compiler.

  • A xvalue is a glvalue that denotes an object or bit-field whose resources can be reused. It has an address that no longer accessible by the program, but can be used to initialize an rvalue reference. Examples include function calls that return an rvalue reference, and the array subscript, member, and pointer to member expressions where the array or object is an rvalue reference.

  • An lvalue is a glvalue that is not an xvalue. It has an address that the program can access. An example is the variable names.

  • An rvalue is a prvalue or an xvalue.

The following figure illustrates the relationships between the categories.

1
2
3
4
5
        expression
          /   \
    glvalue   rvalue
     /   \     /   \
lvalue    xvalue    prvalue

An Example

The following example demonstrates several correct and incorrect usages of lvalues and rvalues:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int main()
{
    int i, j, *p;

    // Correct usage: the variable i is an lvalue and the literal 7 is a prvalue.
    i = 7;

    // Incorrect usage: The left operand must be an lvalue (C2106).`j * 4` is a prvalue.
    7 = i; // C2106
    j * 4 = 7; // C2106

    // Correct usage: the dereferenced pointer is an lvalue.
    *p = i;

    // Correct usage: the conditional operator returns an lvalue.
    ((i < 3) ? i : j) = 7;

    // Incorrect usage: the constant ci is a non-modifiable lvalue (C3892).
    const int ci = 7;
    ci = 9; // C3892
}




Related Posts

Value Categories in C++

Every C++ expression has a type and belongs to a...

Lambda Expressions in C++

A lambda expression is a convenient way of defining an...

Implicit Type Conversions in C++

C++ transforms the operands to a common type before performing...

Explicit Type Conversions in C++

An explicit conversion is also called as a cast. There...

Inline Functions in C++

A function specified as inline is expanded everywhere it is...

Function Pointers in C++

A function pointer is a pointer that denotes a function...