2009-05-09 9 views
20

Jedną z nowych fajnych cech nadchodzącego standardu C++, C++ 0x, są "odniesienia rvalue". Odwołanie RValue jest podobna do lwartością (normalny) odniesienia, poza tym, że może ona być związana z wartością tymczasowego (normalnie, tymczasowy może być związany tylko z const odniesienia):Dlaczego wartość rwartości w C++ 0x nie jest domyślna?

void FunctionWithLValueRef(int& a) {...} 
void FunctionWithRValueRef(int&& a) {...} 

int main() { 
    FunctionWithLValueRef(5); // error, 5 is a temporary 
    FunctionWithRValueRef(5); // okay 
} 

Więc dlaczego oni wymyślić zupełnie nowy typ, zamiast po prostu usunąć ograniczenia normalnych odniesień, aby mogły być powiązane z tymczasowymi?

+3

Zastanawiam się, dlaczego dostałem 3 głosy w górę, ale 7 ulubionych. Nie sądzę, żebym kiedykolwiek faworyzował pytanie bez jego głosowania (chyba że byłbym poza głosami lub był zamknięty). – Zifre

+3

Zastanawiam się, dlaczego ktoś myśli w jakiś sposób, a następnie oczekuje, że wszyscy inni będą robić to samo, co on. – user534498

+1

Zastanawiam się, dlaczego "bycie miłym i dawanie uprowadzenia" jest nieuzasadnionym oczekiwaniem. –

Odpowiedz

43

Byłoby to bezcelowe. Zmieniłbyś rzecz w funkcji, a zmiana zostałaby natychmiast utracona, ponieważ rzecz była w rzeczywistości chwilowa.

Powód nowego typu wynika z potrzeby decydowania o tym, co faktycznie jest wartością rażenia, a co nie. Tylko wtedy możesz je wykorzystać do fajnych rzeczy, które są używane.

string toupper(string && s) { // for nonconst rvalues 
    for(char &c : s) make_uppercase(c); 
    return move(s); // move s into a returned string object 
} 

string toupper(string const& s) { // for the rest 
    // calls the rvalue reference version, by passing 
    // an rvalue copy. 
    return toupper(string(s)); 
} 

Teraz, jeśli masz jakieś rvalue i przekazać go do TOUPPER The RValue mogą być bezpośrednio modyfikowane, ponieważ wiemy, że tymczasowy jest rzeczą jednorazowe i tak, więc możemy aswell wystarczy zmienić go i don” t potrzebujesz go skopiować. Również ta sama obserwacja jest używana do rzeczy zwanej konstruktorem ruchu i przeniesieniem. Prawa strona nie jest kopiowana, ale jej rzeczy są po prostu skradzione i przeniesione do *this.

Jeśli miałbyś powiedzieć, że wartości r można powiązać z niestanowiącymi wartościami lwartości, to nie będziesz w stanie określić, czy odnosi się to do lwartości (nazwanego obiektu), czy też wartości r (na końcu).


To chyba niewiele więcej wiem, ale przydatny w każdym razie, można umieścić lwartości lub rvalue Ref-kwalifikacyjne na funkcję członka. Oto przykład, który w naturalny sposób rozszerza istniejące semantyki referencji rvalue do niejawnego parametru obiektu:

struct string { 
    string& operator=(string const& other) & { /* ... */ } 
}; 

Teraz nie można już powiedzieć

string() = "hello"; 

Który jest mylące i nie jest tak naprawdę czyni czuć przez większość czasu. To, co powyżej, mówi, że operator przypisania może być wywoływany tylko na wartościach l. To samo można zrobić dla wartości r, umieszczając &&.

+1

+1 Wow dziękuję za ostatnią część dotyczącą lvalues ​​/ rvalues ​​tylko członek call!Czytałem dużo o C++ 0x, ale nic nie widziałem (domyślam się, że jest w ostatniej wersji, ale nie przeczytałem tego wszystkiego). Czy możesz wskazać mi jakąś dokumentację dotyczącą tej funkcji? – Klaim

+0

Oto ładny przegląd: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm. W dokumencie roboczym patrz: 8.3.5, 9.3.1 i 13.3.1. –

+0

Dziękuję za tę odpowiedź, dzięki czemu jest ona bardziej przejrzysta. Po prostu nie bardzo rozumiałem odniesienia do rvalue. To ma dużo więcej sensu niż to, co myślałem. – Zifre

12

Ponieważ dodanie nowego rodzaju odniesienia pozwala pisać dwa przeciążeniem metody:

void CopyFrom(MyClass &&c) 
{ 
    dataMember.swap(c); 
} 

void CopyFrom(const MyClass &c) 
{ 
    dataMember.copyTheHardWay(c); 
} 

Wersja, która przyjmuje nowy rodzaj odniesienia może modyfikować zmienną to odbiera, ponieważ zmienna ISN będą używane gdziekolwiek indziej. Więc może "ukraść" jego zawartość.

To jest powód dodania tej funkcji; zachowanie jednego rodzaju odniesienia nie doprowadziłoby do osiągnięcia pożądanego celu.