Q: почему _rvalues_ были переименованы в _prvalues_? (чистые значения)

Этот документ является источником этих изменений по сравнению с C++ 11: n3055.

II.Обзор изменений

Rvalues, как в настоящее время известно в основных предложениях языка, переименовывается в "prvalues" ("чистые" rvalues).

Значение lvalues не изменилось, но были введеныglvalues для охвата xvalues.

Почему бы не сделать то же самое длязначений?

Значение rvalues должно было остаться неизменным, но ввестиgrvalues, чтобы охватить и xvalues. (значения могут быть заменены на простыезначения в симметрии с тем, как определяются значения)

      expression
      /        \
   glvalue    grvalue
   /     \    /     \
lvalue   xvalue   rvalue

Значения категорий можно определить более просто:

  • lvalue имеетидентичность, но не может быть удален; это glvalue, который не является xvalue
  • значение не имеет идентичности, но может быть удалено; это grvalue, который не является xvalue
  • xvalue имеет идентичность и может быть перемещен из.

Каждое выражение является либо lvalue, xvalue или rvalue.

1 ответ

Понятие rvalues ​​было сделано более общим, и сущность rvalues ​​была определена как отсутствие псевдонимов. Была добавлена ​​новая категория значений, xvalues, которая разделяет это свойство, а подмножество rvalues, которое присутствовало до C++11, было переименовано в prvalues ​​("чистые rvalues").

Два основных раздела, которые мы хотим получить, теперь таковы:

  • glvalue против prvalue: glvalue- это объекты (= места хранения); prvalues ​​являются традиционными "временными" (но см. ниже).
  • lvalue vs rvalue: lvalue связывается со ссылками lvalue, rvalue связывается со ссылками rvalue. Это различие необходимо для определения работы ссылок и привязки ссылок.

Xvalue- это и glvalue, и rvalue. Это отражает тот факт, что ссылки на rvalue- это способ выполнить преобразование lvalue в xvalue (через приведение, std::move), то есть иметь определенные пользователем значения. Они также допускают преобразование в другом направлении, из prvalue в lvalue, путем привязки rvalue к ссылке rvalue (которая теперь является lvalue).

C++ 17 уточняет идею немного дальше, превращая prvalues ​​в "условные значения" или "нематериализованные значения", которые больше не являются объектами. На этой новой картине только объекты являются объектами. Однако значения могут быть материализованы в объекты, которые соответственно называются "преобразованием значения в значение".

Этот новый способ мышления о категориях значений означает, что если у вас есть функция T f();, где T не ссылка, то выражение f() сам по себе не является объектом (следовательно, не требует копирования объектов!), но при необходимости (например, если вы говорите f().x), объект создается и инициализируется значением prvalue (= materialized), чтобы разрешить доступ к элементу.


Может быть, стоит обобщить все преобразования, которые существуют в C++ 17:

  • "glvalue-to-prvalue": это то, что C называет "преобразованием lvalue". Пример: int a = 1; 1 + a; Второй операнд выражения сложения является prvalue, полученным преобразованием glvalue-prvalue в a,

  • "rvalue-to-lvalue": Предоставляется ссылками rvalue. Пример: int && r = e, Вот e является выражением Rvalue, и r является lvalue, обозначающим тот же (или потенциально материализованный) объект.

  • "prvalue-to-glvalue": это материализация prvalue, где ожидается glvalue.

  • "lvalue-to-rvalue": доступно только как "lvalue-to-xvalue" через std::moveнапример, int a; static_cast<int&&>(a);,

Обратите внимание, что все пары, которые появляются в списке, имеют одинаковое количество букв - либо обе имеют одну букву, либо обе имеют две. Я думаю, что это является следствием правильно выбранной таксономии, которой нет в предложенной вами альтернативе.

Другие вопросы по тегам