Этот документ является источником этих изменений в C ++ 11: n3055.
II. Обзор изменений
Rvalues, как в настоящее время известно в основных предложениях языка, переименовывается
чтобы «prvalues»(« Чистые »значения).
lvalues смысл не изменился, но glvalues были представлены для покрытия xvalues.
Почему бы не сделать то же самое для rvalues?!
rvalues смысл должен был остаться без изменений, но ввести grvalues покрывать xvalues тоже.
(prvalues можно заменить обратно на простой rvalues в симметрии с тем, как lvalues определены)
expression
/ \
glvalue grvalue
/ \ / \
lvalue xvalue rvalue
Ценовые категории можно определить более просто:
Каждое выражение является либо именующий, xvalue или же Rvalue.
Понятие rvalues было сделано более общим, и сущность rvalues была определена как отсутствие псевдонимов. Была добавлена новая категория значений, xvalues, которая разделяет это свойство, а подмножество rvalues, которое присутствовало до C ++ 11, было переименовано в prvalues («чистые rvalues»).
Два основных раздела, которые мы хотим получить, теперь таковы:
Xvalue — это и glvalue, и rvalue. Это отражает тот факт, что ссылки на rvalue — это способ выполнить преобразование lvalue в xvalue (через приведение, std::move
), то есть иметь определяемые пользователем значения. Они также позволяют преобразование в другом направлении, из prvalue в lvalue, путем привязки rvalue к ссылке rvalue (которая теперь является lvalue).
C ++ 17 уточняет идею немного дальше, превращая prvalues в «условные значения» или «нематериализированные значения», которые больше не являются объектами. На этой новой картине только объекты являются объектами. Однако значения могут быть материализованные в объекты, которые соответственно называются «преобразованием prvalue-to-glvalue».
Этот новый способ мышления о категориях значений означает, что если у вас есть функция 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);
,
Обратите внимание, что все пары, которые появляются в списке, имеют одинаковое количество букв — либо обе имеют одну букву, либо обе имеют две. Я думаю, что это является следствием правильно выбранной таксономии, которой нет в предложенной вами альтернативе.
Других решений пока нет …