[Перевод] lvalues, rvalues, glvalues, prvalues, xvalues, помогите! -
Отсебятина
Оригинальный заголовок: lvalues, rvalues, glvalues, prvalues, xvalues, help! Хабр не разрешает поставить восклицательный знак в конце заголовка.
Случайно попалась эта довольно старая статья 2018 года с простым и понятным описанием категорий значений в C++. До неё всякие glvalue, prvalue, xvalue были малопонятными для меня.
cppreference.com просто перечисляет категории, и это не добавляет понимания, всё кажется чрезмерно излишним.
На stackoverflow.com есть 24 поста разной степени ценности, что только добавляет недоумения от сложности этой темы. Там уже есть картинки, которые призваны упростить понимание, например такие:
Привыкли к lvalue и rvalue, а здесь оказывается, что они вообще рядом не стояли
Здесь с привычными примерами может быть чуточку понятней
Но это всё довольно быстро забывается, продолжаешь пользоваться привычными lvalue и rvalue, и всякие гуру на stackoverflow минусуют тебя, если ты неправильно назвал rvalue вместо prvalue, или пишут комментарии или свои ответы, которые может быть и не лучше твоих, но публика любит плюсовать те ответы, которые используют малопонятные сложные термины, демонстрирующие превосходство знаний.
Понимание категорий значений C++ важно для написания эффективного кода, особенно в прикладных библиотеках, чтобы не допускать ошибок, когда компилятор выбирает не те перегруженные функции, которые ожидаешь, или ошибки неоднозначного выбора таких функций.
Предлагаемая статья очень лёгкая, помогла мне понять, что такое сложное устройство — необходимое, совсем не сложное и легко запоминается.
Собственно перевод
Вы уже привыкли к интуитивному определению «lvalue» и «rvalue», но всё ещё путаетесь насчёт glvalue, xvalue и prvalue и тревожитесь из-за того, что lvalue и rvalue могут меняться? Цель этой статьи — развить вашу интуицию на все эти пять категорий.
Предупреждаю, эта статья не стремится дать полное определение этим пяти категориям значений. Вместо этого, я надеюсь научить вас интуитивно понимать их, когда потребуются детали о них.
Были две категории до C++11 — lvalue и rvalue. Они интуитивно понятны, lvalue — это что-то, имеющее имя, такие, как переменные, и rvalue — это что-то временное:
Потом появились rvalue-ссылки и семантика перемещения. На первый взгляд, старых lvalue / rvalue всё ещё достаточно: нельзя перемещать lvalue (они могут использоваться позже), можно перемещать lvalue (они же временные):
Почему я выделяю красным «Нельзя переместить» и «lvalue»? Ведь может оказаться, что вы хотите переместить некоторые lvalue! Например, у вас есть lvalue, который вы больше не хотите использовать, вы можете привести его к rvalue-сслыке с помощью std::move()
. Любая функция тоже может вернуть rvalue-ссылку на объект с именем.
То есть получается, что-то, что имеет имя и что-то, что может быть перемещено — ортогональны, не связаны между собой. Мы вскоре решим проблему перемещения lvalue, но сейчас давайте изменим нашу диаграмму, чтобы отобразить ортогональный вид этого мира:
Ясно, что чего-то не хватает в левом нижнем углу. (Мы можем игнорировать правый верхний угол, потому что временные объекты, которые не могут быть перемещены — бесполезная концепция.)
C++11 представил новую категорию «xvalue» для lvalue, которые могут быть перемещены. Полезно думать об «xvalue» как «eXpiring lvalue» («умирающее lvalue»), потому что они, вероятно, заканчивают свои жизни и готовы к перемещению (например, функция вернула rvalue-ссылку).
Дополнительно, то, что раньше называлось «rvalue», было переименовано в «prvalue», что значит «pure rvalue» («чистое rvalue»). Это три основные категории:
Но мы ещё не пришли к тому, что же такое «glvalue», и что такое теперь «rvalue». Это выглядит так, будто мы уже объяснили эти концепты! Просто мы ещё не дали им правильных имён и не нарисовали.
glvalue, или «generalized lvalue» («обобщённое lvalue»), в точности покрывает всё, что «имеет имя», игнорируя перемещаемость. rvalue покрывает всё, что может быть перемещено, игнорируя имя. И это всё! Теперь вы знаете все 5 категорий значений.
Если вам понравился этот пост, вы можете подписаться на блоги автора или следить за его Twitter.