2012-07-20 23 views
22

Próbuję zrozumieć koncepcje C++ 11.Jakie wyrażenia tworzą wartości x?

Standardowy projekt, który mam mówi:

xvalue (an „upływającym” value) również odnosi się do obiektu, zwykle pod koniec jego trwania (tak, aby jego zasoby mogą zostać przeniesione, na przykład). Wartość x jest wynikiem pewnych rodzajów wyrażeń obejmujących wartości rvalue (8.3.2). [Przykład: Wynikiem wywołania funkcji, której typem powrotu jest wartość ralenowa , jest wartość x. -end przykład]

OK, więc co dokładnie że "pewne rodzaje wyrażeń", które produkują xvalues? Ta część specyfikacji nie zawiera szczegółowej listy tych wyrażeń.

Rozumiem wartość i prwartość (przynajmniej myślę, rozumiem).

+2

Kompletna odpowiedź: [Czym są wartości r, wartości l, x wartości, wartości gl i wartości prody?] (Http://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues) – pmr

+1

Ta część normy wyjaśnia ogólne pojęcie tego terminu. Nie wyszczególnia każdego rodzaju wyrażenia, które generuje xvalue. Tak dzieje się gdzie indziej w standardzie. –

+0

@NicolBolas: Przeczytałem to pytanie i udzielono odpowiedzi przedtem, dlatego postanowiłem zamieścić kolejne pytanie z tego powodu. – PermanentGuest

Odpowiedz

18

Jest to przydatne dla normatywne uwaga na wstępie §5 (C++ 11 § 5 [wyrażenie]/6):

[Uwaga: Wyrażenie to xvalue jeśli to jest:

  • wynikiem wywołania funkcji, czy jawnie lub niejawnie, którego zwrot typ jest odniesienie do rValue typu obiektu,

  • odlew z referencyjną rvalue do obiektu typu

  • wyrażenie dostępu członka klasy wyznaczania niż statycznego elementu danych typu niereferencyjnego w których ekspresja przedmiot jest xvalue lub

  • wyrażenie, w którym pierwszy operand .* wskaźnik do członka x wartość i drugi operand to wskaźnik do elementu danych.

Na ogół, efekt tego przepisu jest to, że wymienione odniesienia RValue są traktowane jako lwartościami i nazwanych RValue odwołań do obiektów są traktowane jako xvalues; Wartości rvalue dla funkcji są traktowane jako l-wartości, niezależnie od tego, czy są nazwane, czy nie. -end note]

Przeszukując resztę §5, lista ta jest wyczerpująca. Lista jest następnie przykład:

struct A { 
    int m; 
}; 

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

Wyrażenia f(), f().m, static_cast<A&&>(a) i a + a są xvalues. Wyrażenie ar jest wartością l.

Istnieją dwa sposoby, aby uzyskać wyrażenie xvalue:

  • Zastosowanie std::move Aby przenieść obiekt. std::move wykonuje static_cast dla typu odniesienia rwartości i zwraca referencję rvalue.

  • Użyj std::forward, aby przesłać wartość r. std::forward jest zwykle używany w szablonie funkcji, aby umożliwić doskonałe przekazywanie argumentu funkcji.

    Jeśli argument podany w szablonie funkcji był wartością r, typ parametru będzie wartością rvalue, która jest lwartością. W tym przypadku std::forward wykonuje static_cast dla typu odniesienia rVue i zwraca referencję rvalue.

    (Uwaga: Jeśli argument dostarczane do matrycy funkcja została lwartością, typu parametru będzie odniesienie lwartość i std::forward powróci lwartością odniesienie.)

+1

Boo, tak jak budowałem listę przykładów i natknąłem się na cytat. :(+1, powinienem zrobić edycję znaczka po skończeniu mojej odpowiedzi :) – Xeo

+0

Dzięki za szczegółową listę ... to w połączeniu z innymi odpowiedziami i wieloma innymi metodami googlowania nieco wyjaśniło zamieszanie w stosunku do podstawowej definicji. – PermanentGuest

+0

Bardzo przydatna odpowiedź, ale jeden punkt wciąż wymyka się mojemu zrozumieniu. Rozumiem, że w 'Foo bar() {Foo foo; return foo;} ', wyrażenie' foo' jest xvalue w instrukcji return (proszę poprawić, jeśli jest źle). Nie widzę, żeby była objęta listą, którą cytowałeś. – ricab

6

§ 5, który opisuje składnię poprawnych wyrażeń, listy dla każdej składni wyrażenia warunki, w których wyrażenie jest lwartością, xwartością lub prwartością. Pełna lista możliwych x wartości z punktu 5 to:

5.2.2 punkt 10: Wywołanie funkcji jest ... x wartością, jeśli typ wyniku jest referencją rwartości do typu obiektu.

(W języku technicznym Standardu „typ obiektu” nie znaczy to samo co „typu klasy.” „Obiekt” zawiera podstawowe typy, wskaźniki i tablice, a nie obejmuje jedynie rodzaje funkcji. Odwołanie do typu r funkcji jest zawsze traktowane jako l, a nie jako wartość.)

Najbardziej znaczącymi funkcjami, które zwracają wartość odniesienia r, są oczywiście std::move, a czasami std::forward.

5.2.5 ustęp 4: Jeżeli E2 jest non-static członek dane ... jeśli E1 jest xvalue, następnie E1.E2 jest xvalue

(Z drugiej strony, członek dane wyszukiwanie E1->E2 zawsze lwartością)

Podobnie, E1 jest xvalue, wówczas wyszukiwanie element danych E1.*E2 jest xvalue.

5.5 paragraf 6: Wynik wyrażenia .*, którego drugi operand jest wskaźnikiem do elementu danych, należy do tej samej kategorii wartości (3.10), co jego pierwszy operand.

Dla różnych rodzajów odlewów:

  • dynamic_cast<Type>(expr): 5.2.7 ustęp 2
  • static_cast<Type>(expr): 5.2.9 ustęp 1
  • reinterpret_cast<Type>(expr): 5.2.10 ustęp 1
  • const_cast<Type>(expr) : 5.2.11 paragraf 1
  • (Type) expr: 5.4 paragraf 1

Wyrażenie ma wartość x wtedy i tylko wtedy, gdy Type jest referencją rwartości do typu obiektu.To samo odnosi się również do , ponieważ

5.2.3 pkt 1: Jeżeli lista wyraz [w nawiasach po nazwie Type] jest pojedynczy wyraz, wyrażenie typu konwersja jest równoważny (w definedness, a jeśli zdefiniowane w znaczeniu) do odpowiedniego wyrażenia rzutowania (5.4).

(Z drugiej strony, Type{expr} zawsze prvalue).

Rozdział 5.16 od operatora warunkowego kończy się mówi, że A ? B : C może być czasem xvalue gdy B i/lub C jest xvalue. Ale pełne reguły są trudne do podsumowania.

Jeśli wyraz kończy się wywołanie funkcji przeciążony operatora zdefiniowanego przez użytkownika, a następnie sekcja 5.2.2 stosuje się do tej wypowiedzi, a nie ten, który opisuje wbudowany zachowanie operatora. (Patrz wyrażenie a + a w przykładzie @James pisał.)

0

Co wnoszę z tego co czytałem to, że nazywając coś xvalue to fantazyjny sposób na powiedzenie:

xvalue właśnie rvalue którego Magazyn mógł zostać zwolniony, więc użycie go oznacza, że ​​musisz sam zweryfikować jego istnienie.

Zasadniczo jest to jeden lub więcej poziomów niezależności od rzeczywistej wartości r.

W przeciwieństwie do nich, rura ma zagwarantowaną przestrzeń do przechowywania, o ile jest w zasięgu.

Mogę się mylić, ale to właśnie zrozumiałem.

+5

Nie, wartość x jest wartością, która jest nadal ważna, ale ma zostać odrzucona.Co generalnie oznacza, że ​​można bezpiecznie robić takie rzeczy, jak "kradną" z niego zasoby i zapisywać dotychczasową wartość. – aschepler

+0

@spróbka: np. typ zwracany '[]() {int x = 5; return std :: move (x); } 'nie jest wartością x? Jeśli nie, to co to jest? – Mehrdad

+2

Typy nie mają kategorii wartości; wyrażenia zrobić. – aschepler