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);
,
Обратите внимание, что все пары, которые появляются в списке, имеют одинаковое количество букв - либо обе имеют одну букву, либо обе имеют две. Я думаю, что это является следствием правильно выбранной таксономии, которой нет в предложенной вами альтернативе.