2012-07-20 1 views
22

Я пытаюсь понять концепции C++ 11.Какие выражения создают значения xvalues?

стандартный проект, который меня говорит:

xvalue («истекающий срок действия» значение) также относится к объекту, как правило, ближе к концу своей жизни (так, что его ресурсов могут быть перемещены, например). Значение x является результатом определенных видов выражений с использованием ссылок rvalue (8.3.2). [Пример: результат вызова функции, тип возврата которой является значением rvalue , является значением xvalue. -end пример]

ОК, так что именно являются на «определенные виды выражений», которые производят xvalues? Эта часть спецификации не детализирует список этих выражений.

Я понимаю lvalue и prvalue (по крайней мере, я думаю, я понимаю).

+2

Полный ответ: [Что такое rvalues, lvalues, xvalues, glvalues ​​и prvalues?] (Http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) – pmr

+1

Эта часть стандарта объясняет общее понимание термина. Он не детализирует все выражения, генерирующие xvalue. Это происходит в другом месте стандарта. –

+0

@NicolBolas: Я прочитал этот вопрос и ответы раньше, и я решил отправить другой вопрос именно по этой причине. – PermanentGuest

ответ

18

Существует полезный ненормативный примечание во введении к § 5 (С ++ 11 § 5 [выражение]/6):

[Примечание: выражение является xvalue, если это:

  • результат вызова функции, независимо от того, явно или неявно, чьих возвращаемого типа является ссылка Rvalue объекта типа,

  • литых к ссылке RValue объекта типа,

  • выражение доступа члена класса, обозначающее нестатический элемент данных не-опорный типа, в котором выражение объекта является xvalue или

  • .* выражения указателя на член, в котором первый операнд значение x, а второй операнд - указатель на элемент данных.

В общем, эффект этого правила состоит в том, что названные RValue ссылки рассматриваются как lvalues ​​и неназванных RValue ссылки на объекты рассматриваются как xvalues; Ссылки rvalue на функции обрабатываются как lvalues, имена или нет. -end note]

Поиск в остальной части §5, этот список представляется исчерпывающим. Список следует пример:

struct A { 
    int m; 
}; 

A&& operator+(A, A); 
A&& f(); 
A a; 
A&& ar = static_cast<A&&>(a); 

Выражения f(), f().m, static_cast<A&&>(a) и a + a являются xvalues. Выражение ar является значением lvalue.

Есть два основных способа получить выражение xvalue:

  • Использование std::move для перемещения объекта. std::move выполняет команду static_cast на ссылочный тип rvalue и возвращает ссылку rvalue.

  • Используйте std::forward, чтобы переслать rvalue. std::forward обычно используется в шаблоне функции, чтобы обеспечить идеальную пересылку аргумента функции.

    Если аргумент, предоставленный шаблону функции, был rvalue, тип параметра будет ссылкой rvalue, которая является значением lvalue. В этом случае std::forward выполняет static_cast для ссылочного типа rvalue и возвращает ссылку на rvalue.

    (Примечание: Если аргумент при условии, чтобы шаблон функции был именующим, тип параметра будет ссылкой Левой и std::forward будет возвращать именующую ссылку.)

+1

Бу, так же, как я строю свой список примеров и наткнулся на цитату. :(+1, должно было сделать редактирование тега после того, как я закончил свой ответ. :) – Xeo

+0

Спасибо за подробный список ... это в сочетании с другими ответами и множеством других поисковых запросов несколько очистило путаницу по основному определению. – PermanentGuest

+0

Очень полезный ответ, но один момент все еще ускользает от моего понимания. Я понимаю, что в 'Foo bar() {Foo foo; return foo;} ', выражение' foo' является значением xval в возвращаемом выражении (пожалуйста, исправьте, если не так). Я не вижу, чтобы это охватывало список, который вы цитировали. – ricab

6

пунктом 5, в котором описывается синтаксис действительных выражений, списки для каждого синтаксиса выражения - условия, в которых выражение является значением lvalue, значением x или значением prvalue. Полный список возможных значений x из пункта 5:

5.2.2 параграф 10: вызов функции является ... значением xvalue, если тип результата является ссылкой rvalue на тип объекта.

(В техническом языке Стандарта, «тип объекта» не означает то же самое, как «класс типа». «Тип объекта» включает в себя основные типы, указатели и массивы, и исключает только типы функций. Ссылка rvalue на тип функции всегда обрабатывается как lvalue, а не xvalue.)

Наиболее заметными функциями, которые возвращают ссылку на rvalue, являются, конечно, std::move, а иногда и std::forward.

5.2.5 пункта 4: Если E2 не является статическим членом данных ... если E1 является xvalue, то E1.E2 является xvalue

(С другой стороны, член данных поиск E1->E2 всегда именующий)

Аналогичен, если E1 является xvalue, то поиск члена данных E1.*E2 является xvalue:.

5.5 параграф 6: результат выражения .*, второй операнд которого является указателем на элемент данных, имеет такую ​​же категорию значений (3.10), что и его первый операнд.

Для различных типов отливок:

  • dynamic_cast<Type>(expr): 5.2.7 пункта 2
  • static_cast<Type>(expr): 5.2.9 пункт 1
  • reinterpret_cast<Type>(expr): пункт 5.2.10 1
  • const_cast<Type>(expr) : 5.2.11, пункт 1
  • (Type) expr: 5.4 параграф 1

выражение является значением xvalue тогда и только тогда, когда Type является ссылкой rvalue на тип объекта.То же самое верно и для , поскольку в пункте 1

5.2.3: Если список выражений [в скобках после имени типа] является одно выражение, выражение преобразования типа эквивалентно (в определенность, и если определенный по смыслу) соответствующему литовому выражению (5.4).

(С другой стороны, Type{expr} всегда prvalue.)

Раздел 5.16 на условный оператор заканчивает говорить, что A ? B : C иногда может быть xvalue, если В и/или С является xvalue. Но полные правила трудно подвести итогами.

Если выражение заканчивается вызовом пользовательской перегруженной операторской функции, то к этому выражению применяется раздел 5.2.2, а не тот, который описывает поведение встроенного оператора. (См выражение a + a в примере @James вывешенным.)

0

Что я понял из того, что я прочитал, что называя собой нечто xvalue это причудливый способ сказать:

xvalue это просто Rvalue которого хранилище, возможно, было освобождено, поэтому его использование означает, что вы должны сами проверить его существование.

Как правило, это один или несколько уровней косвенности от фактического значения rvalue.

В отличие от этого у rvalue гарантируется наличие существующего пространства для хранения до тех пор, пока оно находится в области видимости.

Возможно, я ошибаюсь, но это то, что я понял.

+5

Нет, значение xvalue является значением, которое все еще действует, но должно быть отброшено.Как правило, это означает, что можно безопасно делать такие вещи, как «украсть» ресурсы и написать над своим существующим значением. – aschepler

+0

@aschepler: Так, например, возвращаемый тип '[]() {int x = 5; return std :: move (x); } 'не является значением xvalue? Если нет, то что это? – Mehrdad

+2

Типы не имеют категорий значений; выражения. – aschepler