Значения Lvalue и Rvalue (C++)
Каждое выражение C++ имеет тип и принадлежит категории значений. Категории значений являются основой правил, которые компиляторы должны следовать при создании, копировании и перемещении временных объектов во время оценки выражений.
Стандарт C++17 определяет категории значений выражений следующим образом:
- Glvalue — это выражение, оценка которого определяет удостоверение объекта, битового поля или функции.
- Prvalue — это выражение, вычисление которого инициализирует объект или битовое поле, или вычисляет значение операнда оператора, как указано в контексте, в котором он отображается.
- Xvalue — это glvalue, обозначающее объект или битовое поле, ресурсы которого можно повторно использовать (как правило, так как оно находится в конце его существования). Пример. Некоторые типы выражений с использованием ссылок rvalue (8.3.2) дают xvalues, например вызов функции, тип возвращаемого значения которой является ссылкой rvalue или приведением к типу ссылки rvalue.
- Lvalue — это glvalue, которое не является xvalue.
- Rvalue — это prvalue или xvalue.
На следующей схеме показаны связи между категориями:
Схема начинается с поля с помеченным выражением, которое имеет два дочерних элемента: 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: &&
Обратная связь
https://aka.ms/ContentUserFeedback.
Ожидается в ближайшее время: в течение 2024 года мы постепенно откажемся от GitHub Issues как механизма обратной связи для контента и заменим его новой системой обратной связи. Дополнительные сведения см. в разделеОтправить и просмотреть отзыв по