Numer referencyjny l można powiązać z dowolnym. Wartość rvalue reference może być powiązana tylko z wartościami rvalues innych niż const
.
non-const lvalue const lvalue non-const rvalue const rvalue
const T& yes yes yes yes
T&& no no yes no
Jak widać, są bardzo różne.
Ponadto, jeśli wywołanie funkcji zwróci wartość odniesienia l, to wyrażenie jest lwartością, ale jeśli wywołanie funkcji zwraca referencję rwartości do obiektu, to wyrażenie jest wartością x.
Połączenie funkcja lwartością jeśli typ rezultacie lwartością typu odniesienia lub referencją RValue rodzaju funkcję, do xvalue jeśli typ wynik jest odniesienie RValue na typ obiektu, a prvalue inaczej.
Co do tego, kiedy chciałbyś zmodyfikować wartość rundy - cóż, właśnie o to chodzi w seansie ruchu. Rozważmy następujące wywołanie funkcji:
void func(std::string);
func(std::string("Hello"));
Wyrażenie std::string("Hello")
jest rvalue że tworzy tymczasowy obiekt. Podczas inicjowania parametru std::string
z tą wartością, wybierze konstruktora, który pobiera referencję rvalue - konstruktor ruchu. Konstruktor ten następnie kradnie rzeczy z wartości runtue, co jest zazwyczaj znacznie szybsze niż wykonanie pełnej kopii. Możemy go ukraść, ponieważ wiemy, że jest tymczasowy.
Co do kiedy należy zwrócić const
referencje lwartości lub rvalue nazwy:
Zwracanie const
lwartość odniesienia jest najczęściej stosowany, gdy chcesz dać dostęp do odczytu „wewnętrzne” obiekt (być może członkiem klasy), ale nie pozwalają go modyfikować.
Zwrot referencyjny rvalue jest najczęściej używany (w ogóle nie jest powszechny), gdy chcemy zezwolić na wywoływanie kodu, aby przejść z "wewnętrznego" obiektu (być może członka klasy). Zamiast przesuwania się z tymczasowo zwróconego obiektu (tak jak przy zwracaniu przez wartość), dosłownie przemieszczają się one z obiektu wewnętrznego.
ten można także osiągnąć za pomocą nie- const
odniesienia lwartości, ale wtedy musiałby wyraźnie std::move
to.
Jest więc mało prawdopodobne, że będziesz musiał zwrócić referencję rvalue.
Nie oznacza to, że std::forward
ma typ zwrotu, który wygląda jak T&&
. Jest to jednak złudne, ponieważ może, ale nie musi być wartością rvalue, w zależności od typu T
. Zobacz universal references.
Tak, zgaduję. Będę edytować post ... – jbgs
Jeśli mówisz o ** powrocie **, to prawdopodobnie nie chcesz zwrócić * referencji rvalue *. Chociaż może istnieć jakaś przypadek użycia, który mógłby zostać wdrożony przez zwrócenie wartości * rvalue-reference *, w większości sytuacji spowoduje to niezdefiniowane zachowanie. –