Ответ
lvalue (left-hand value) — это выражение, которое обозначает объект, занимающий идентифицируемое место в памяти (т.е. имеющий адрес). Его время жизни выходит за рамки одного выражения. Ключевое свойство lvalue — к нему можно применить оператор взятия адреса &.
Характеристики и примеры lvalue:
- Имена переменных (как фундаментальных, так и пользовательских типов).
int x = 42; // `x` — lvalue std::vector<int> vec; // `vec` — lvalue - Ссылки всегда являются lvalue.
int& ref_x = x; // `ref_x` — lvalue (ссылается на `x`) - Результат обращения к элементу по индексу или имени, если контейнер возвращает ссылку.
vec[0] = 10; // `vec[0]` — lvalue (operator[] у std::vector возвращает T&) - Разыменованный указатель.
int* ptr = &x; *ptr = 100; // `*ptr` — lvalue - Строковые литералы (в C++ они имеют тип
const char[N]и хранятся в памяти).const char* p = "hello"; // `"hello"` — lvalue - Функции. Имя функции — lvalue.
Важное уточнение: lvalue не обязательно может находиться слева от оператора присваивания. Константные lvalue (const int c = 5;) являются неизменяемыми.
Практическое значение: Понимание категорий значений (lvalue, rvalue, xvalue, prvalue, glvalue) критически важно для:
- Работы с ссылками: Невозможно инициализировать неконстантную lvalue-ссылку (
int&) rvalue.int& a = 10; // Ошибка: 10 — rvalue const int& b = 10; // OK: const lvalue-ссылку можно биндить к rvalue - Использования семантики перемещения: Правила выбора перегруженных функций (принимающих
T&илиT&&) основаны на категории передаваемого выражения. - Оптимизаций: Компилятор может применять разные оптимизации в зависимости от того, является ли выражение lvalue.
Ответ 18+ 🔞
Э, слушай, тут про lvalue надо поговорить, а то народ путается, как мартышлюшка с гранатой. Представь себе переменную — это как твоя собственная квартира. У неё есть конкретный адрес, ты можешь туда прийти, поставить диван или выкинуть старый хлам. Вот это и есть lvalue — штука, у которой есть адрес в памяти, и её можно потрогать оператором & (взять адрес).
Короче, кто эти lvalue:
- Имена переменных — это прям классика.
int x = 42;—xэто lvalue, его адрес можно спросить:&x. - Ссылки — они всегда lvalue. Ссылка — это просто погоняло, кличка для уже существующей переменной.
int& ref = x;—refэто lvalue. - Результат разыменования указателя. Указатель — это бумажка с адресом квартиры. А
*ptr— это когда ты по этому адресу пришёл и в дверь пнул. Сама дверь (объект) — lvalue. - Обращение к элементу массива или вектора, если он возвращает ссылку.
vec[5] = 10;—vec[5]это lvalue, потому чтоstd::vector::operator[]возвращает ссылку, ты лезешь прямо в его внутренности. - Строковые литералы в кавычках. Да-да,
"hello"— это тоже lvalue, массив символов где-то в памяти лежит, хоть и константный.const char* p = "hello";— тут"hello"и есть lvalue. - Имена функций. Да, функция — тоже lvalue, у неё есть адрес.
А теперь главный подвох, ёпта! Многие думают, что lvalue — это то, что обязательно можно поставить слева от =. Это пиздопроебибна! Константа — тоже lvalue, но ей присвоить не получится.
const int mega_const = 100500;
// mega_const — lvalue, у него есть адрес (&mega_const).
// mega_const = 0; // А вот это — ошибка, потому что оно const.
Нахуя это всё надо?
А вот нахуя:
- Чтобы не выстрелить себе в ногу со ссылками. Неконстантную lvalue-ссылку (
int&) нельзя привязать к временному значению (rvalue). Компилятор наорет.int& a = 10; // Ошибка: "Э, сабака сука, куда лезешь? 10 — это rvalue, временщик!" const int& b = 10; // А так — ок. Константная ссылка может на всё смотреть. - Чтобы понимать семантику перемещения. Вся эта магия с
T&&(rvalue-ссылки) работает именно потому, что компилятор отличает lvalue (у которого есть имя и адрес) от rvalue (которое можно спиздить). От этого зависит, какую версию функции вызовут. - Для оптимизаций. Зная, что выражение — lvalue, компилятор понимает, что объект живёт дольше одной строчки, и может по-другому с ним работать.
Короче, lvalue — это не просто "слева от равно". Это фундаментальная хуйня в языке, про которую надо знать, иначе будешь как тот полупидор, который std::move на константу применяет и удивляется, почему ничего не переместилось.