Значения Lvalue и Rvalue (C++)

Каждое выражение C++ имеет тип и принадлежит категории значений. Категории значений являются основой правил, которые компиляторы должны следовать при создании, копировании и перемещении временных объектов во время оценки выражений.

Стандарт C++17 определяет категории значений выражений следующим образом:

  • Glvalue — это выражение, оценка которого определяет удостоверение объекта, битового поля или функции.
  • Prvalue — это выражение, вычисление которого инициализирует объект или битовое поле, или вычисляет значение операнда оператора, как указано в контексте, в котором он отображается.
  • Xvalue — это glvalue, обозначающее объект или битовое поле, ресурсы которого можно повторно использовать (как правило, так как оно находится в конце его существования). Пример. Некоторые типы выражений с использованием ссылок rvalue (8.3.2) дают xvalues, например вызов функции, тип возвращаемого значения которой является ссылкой rvalue или приведением к типу ссылки rvalue.
  • Lvalue — это glvalue, которое не является xvalue.
  • Rvalue — это prvalue или xvalue.

На следующей схеме показаны связи между категориями:

Diagram of C++ expression value categories.

Схема начинается с поля с помеченным выражением, которое имеет два дочерних элемента: glvalue и rvalue. glvalue имеет два дочерних элемента: lvalue и xvalue. rvalue имеет два дочерних элемента: prvalue и xvalue; xvalue также является дочерним элементом glvalue.

Lvalue имеет адрес, к которому может получить доступ ваша программа. Примеры выражений lvalue включают имена переменных, включая const переменные, элементы массива, вызовы функций, возвращающие ссылку lvalue, бит-поля, объединения и члены класса.

Выражение prvalue не имеет адреса, доступные вашей программой. Примеры выражений prvalue включают литералы, вызовы функций, возвращающие тип неконференции, и временные объекты, созданные во время оценки выражений, но доступные только компилятором.

Выражение xvalue имеет адрес, который больше недоступен программой, но может использоваться для инициализации ссылки rvalue, которая предоставляет доступ к выражению. К примерам относятся вызовы функций, возвращающие ссылку rvalue, а также подстрочный массив, член и указатель на выражения элементов, где массив или объект является ссылкой rvalue.

Пример

В следующем примере показано несколько правильных и неправильных способов использования значений lvalue и rvalues.

// lvalues_and_rvalues2.cpp
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
}

Примечание.

В примерах этого раздела показано правильное и неправильное использование при неперегруженных операторах. Перегрузив операторы, можно преобразовать выражение, такое как j * 4, в значение lvalue.

Термины lvalue и rvalue часто используются при ссылке на объекты. Дополнительные сведения о ссылках см. в разделе "Декларатор ссылок Lvalue: & иRvalue Reference Декларатор: &>.

См. также

Основные понятия
Декларатор ссылки Lvalue: &
Декларатор ссылки rvalue: &&