lvalues, rvalues, glvalues, prvalues, xvalues, помогите! –

в 4:43, , рубрики: c++, glvalue, lvalue, move-семантика, prvalue, rvalue, value category, xvalue, категория значений, семантика перемещения

Отсебятина

Оригинальный заголовок: lvalues, rvalues, glvalues, prvalues, xvalues, help! Хабр не разрешает поставить восклицательный знак в конце заголовка.

Случайно попалась эта довольно старая статья 2018 года и дополненная в 2019 году с простым и понятным описанием категорий значений в C++. До неё всякие glvalue, prvalue, xvalue были малопонятными для меня.

cppreference.com просто перечисляет категории, и это не добавляет понимания, всё кажется чрезмерно излишним.

На stackoverflow.com есть 24 поста разной степени ценности, что только добавляет недоумения от сложности этой темы. Там уже есть картинки, которые призваны упростить понимание, например такие:

Привыкли к lvalue и rvalue, а здесь оказывается, что они вообще рядом не стояли

Привыкли к lvalue и rvalue, а здесь оказывается, что они вообще рядом не стояли
Здесь с привычными примерами может быть чуточку понятней

Здесь с привычными примерами может быть чуточку понятней

Но это всё довольно быстро забывается, продолжаешь пользоваться привычными lvalue и rvalue, и всякие гуру на stackoverflow минусуют тебя, если ты неправильно назвал rvalue вместо prvalue, или пишут комментарии или свои ответы, которые может быть и не лучше твоих, но публика любит плюсовать те ответы, которые используют малопонятные сложные термины, демонстрирующие превосходство знаний.

Понимание категорий значений C++ важно для написания эффективного кода, особенно в прикладных библиотеках, чтобы не допускать ошибок, когда компилятор выбирает не те перегруженные функции, которые ожидаешь, или ошибки неоднозначного выбора таких функций.

Предлагаемая статья очень лёгкая, помогла мне понять, что такое сложное устройство - необходимое, совсем не сложное и легко запоминается.

Собственно перевод

Вы уже привыкли к интуитивному определению «lvalue» и «rvalue», но всё ещё путаетесь насчёт glvalue, xvalue и prvalue и тревожитесь из‑за того, что lvalue и rvalue могут меняться? Цель этой статьи — развить вашу интуицию на все эти пять категорий.

Предупреждаю, эта статья не стремится дать полное определение этим пяти категориям значений. Вместо этого, я надеюсь научить вас интуитивно понимать их, когда потребуются детали о них.

Были две категории до C++11 — lvalue и rvalue. Они интуитивно понятны, lvalue — это что‑то, имеющее имя, такие, как переменные, и rvalue — это выражения, вычисляющие временные объекты (без имени). Рассмотрим эти определения:

  Widget w;
  Widget getWidget();

Если мы используем выражение w , его результат вывода - это объект w , который имеет имя. Если мы используем выражение getWidget() , его результат вызова - это временный объект без имени. Попробуем иллюстрировать это так:

lvalues, rvalues, glvalues, prvalues, xvalues, помогите! - - 3

Потом появились rvalue-ссылки и семантика перемещения. На первый взгляд, старых lvalue / rvalue всё ещё достаточно: нельзя перемещать lvalue (они могут использоваться позже), можно перемещать rvalue (они же временные):

lvalues, rvalues, glvalues, prvalues, xvalues, помогите! - - 4

Почему я выделяюкрасным «Нельзя переместить» и «lvalue»? Ведь может оказаться, что вы хотите переместить некоторые lvalue! Например, у вас есть lvalue, который вы больше не хотите использовать, вы можете привести его к rvalue-сслыке с помощью std::move() . Любая функция тоже может вернуть rvalue-ссылку на объект с именем.

То есть получается, что-то, что имеет имя и что‑то, что может быть перемещено — ортогональны, не связаны между собой. Мы вскоре решим проблему перемещения lvalue, но сейчас давайте изменим нашу диаграмму, чтобы отобразить ортогональный вид этого мира:

lvalues, rvalues, glvalues, prvalues, xvalues, помогите! - - 5

Ясно, что чего-то не хватает в левом нижнем углу. (Мы можем игнорировать правый верхний угол, потому что временные объекты, которые не могут быть перемещены - бесполезная концепция.)

C++11 представил новую категорию «xvalue» для lvalue, которые могут быть перемещены. Полезно думать об «xvalue» как «eXpiring lvalue» («умирающее lvalue»), потому что они, вероятно, заканчивают свои жизни и готовы к перемещению (например, rvalue‑ссылка из функции).

Дополнительно, то, что раньше называлось «rvalue», было переименовано в «prvalue», что значит «pure rvalue» («чистое rvalue»). Это три основные категории:

lvalues, rvalues, glvalues, prvalues, xvalues, помогите! - - 6

Но мы ещё не пришли к тому, что же такое «glvalue», и что такое теперь «rvalue». Кажется, будто мы уже объяснили эти концепты! Просто ещё не да ли им правильных имён и не нарисовали.

lvalues, rvalues, glvalues, prvalues, xvalues, помогите! - - 7

glvalue, или «generalized lvalue» («обобщённое lvalue»), в точности покрывает всё, что «имеет имя», игнорируя перемещаемость. rvalue покрывает всё, что может быть перемещено, игнорируя имя. И это всё! Теперь вы знаете все 5 категорий значений.

Если вы хотите погрузиться ещё глубже в эту тему, на cppreference есть очень хорошая статья.

Если вам понравился этот пост, вы можете подписаться на блоги автора или следить за его Twitter.

Автор: sergio_nsk

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js