Lvalue и rvalue: различие
Разбирайтесь в категориях значений: lvalue, prvalue и xvalue.
«Lvalue и rvalue: различие» — бесплатный урок C++ Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Два мира: левосторонние и правосторонние значения
Каждое выражение в C++ является либо левосторонним значением (объектом с именем и адресом), либо правосторонним значением (временным объектом без имени).
Левосторонние значения
Левостороннее значение обозначает постоянный объект — его адрес можно получить с помощью &.
int x = 42; // x is an lvalue
int* p = &x; // taking the address of an lvalue
int& r = x; // r is an lvalue referenceПравосторонние значения
Правостороннее значение — это временный объект: литерал, возвращаемое функцией значение или выражение вроде a + b. Получить его адрес нельзя.
int a = 5, b = 3;
int c = a + b; // (a + b) is an rvalue
// int* p = &(a + b); // ERROR: cannot take address of an rvalueПочему это различие важно
Правостороннее значение скоро будет уничтожено. Мы можем безопасно забрать его ресурсы вместо копирования — на этом основана семантика перемещения.
Три категории начиная с C++11
Современный C++ уточняет эту модель:
- левостороннее значение — имеет имя и идентичность
- чистое правостороннее значение — полностью временный объект (литерал или значение, возвращаемое по значению)
- истекающее значение — скоро будет уничтожено (результат
std::move)
Ссылки на левосторонние и правосторонние значения
Ссылка на левостороннее значение использует &, а ссылка на правостороннее значение — &&.
int x = 10;
int& lr = x; // lvalue reference
int&& rr = 42; // rvalue reference, binds to literalПравила связывания
Совместимость типов:
- ссылка на левостороннее значение (
T&) связывается с левосторонними значениями - константная ссылка на левостороннее значение (
const T&) связывается с обоими видами - ссылка на правостороннее значение (
T&&) связывается только с правосторонними и истекающими значениями
Проверка с помощью decltype
С помощью decltype можно попросить компилятор определить категорию выражения.
int x = 10;
static_assert(std::is_lvalue_reference<decltype((x))>::value);
// the extra parentheses make decltype yield the lvalue refЗачем в C++11 добавили ссылки на правосторонние значения
Чтобы обеспечить семантику перемещения: конструктор, принимающий T&&, может забрать внутренние данные временного объекта, избежав глубокого копирования.
Распространённая ошибка: именованная ссылка на правостороннее значение — это левостороннее значение
После объявления переменная-ссылка на правостороннее значение получает имя, поэтому становится левосторонним значением. Чтобы передать её дальше как правостороннее значение, используйте std::move.
void f(std::string&& s) {
// s here is an lvalue!
process(std::move(s)); // now it is an rvalue again
}Предварительный обзор идеальной передачи
Шаблоны, принимающие T&&, выводят либо ссылку на левостороннее, либо ссылку на правостороннее значение. В сочетании с std::forward они могут сохранять категорию значения — подробно это рассматривается далее.
Быстрая проверка
Какое из этих выражений является правосторонним значением?
Итоги
Левостороннее значение имеет имя и адрес, а правостороннее значение является временным. T& связывается с левосторонними значениями, а T&& — с правосторонними. Это различие обеспечивает семантику перемещения и позволяет избегать ненужного копирования временных объектов.
Часто задаваемые вопросы
Урок «Lvalue и rvalue: различие» бесплатный?
Да — полный текст урока «Lvalue и rvalue: различие» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «Lvalue и rvalue: различие»?
Разбирайтесь в категориях значений: lvalue, prvalue и xvalue. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Lvalue и rvalue: различие»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Lvalue и rvalue: различие
- Ссылки rvalue и синтаксис &&
- std::move и std::forward
- Конструкторы перемещения и присваивание перемещением