2017-07-11 12 views
13

Próbowałem zrozumieć lwartości i wartości w C++ 11. Więc napisałem kod testowy:Dlaczego powiązanie odwołania rvalue do wartości xvalue nie działa w moim kodzie?

int x = 10; 
int foo() { return x; } 
int& bar() { return x; } 
int&& baz() { return 10; } 

int main() { 
    int& lr1 = 10;  // error: lvalue references rvalue 
    int& lr2 = x;  // ok 
    int& lr3 = foo(); // error: lvalue references rvalue 
    int& lr4 = bar(); // ok 
    int& lr5 = baz(); // error: lvalue references rvalue 

    int&& rr1 = 10; // ok 
    int&& rr2 = x;  // error: rvalue references lvalue 
    int&& rr3 = foo(); // ok 
    int&& rr4 = bar(); // error: rvalue references lvalue 
    int&& rr5 = baz(); // ok 
} 

działa całkiem dobrze, więc dodaje std :: cout wydrukować wyniki.

#include <iostream> 

int x= 10; 
int foo() { return x; } 
int& bar() { return x; } 
int&& baz() { return 10; } 

int main() { 
    int& lr1 = 10;  std::cout << lr1 << std::endl; // error 
    int& lr2 = x;  std::cout << lr2 << std::endl; // ok 
    int& lr3 = foo(); std::cout << lr3 << std::endl; // error 
    int& lr4 = bar(); std::cout << lr4 << std::endl; // ok 
    int& lr5 = baz(); std::cout << lr5 << std::endl; // error 

    int&& rr1 = 10; std::cout << rr1 << std::endl; // ok 
    int&& rr2 = x;  std::cout << rr2 << std::endl; // error 
    int&& rr3 = foo(); std::cout << rr3 << std::endl; // ok 
    int&& rr4 = bar(); std::cout << rr4 << std::endl; // error 
    int&& rr5 = baz(); std::cout << rr5 << std::endl; // ERROR!? 
} 

int&& rr5 = baz(); std::cout << rr5; powoduje Runtime Error, ale nie wiem, dlaczego to robi błąd.

Myślę, że wartość zwracana baz() byłaby xvalue, więc jego żywotność jest przedłużona. Ale kiedy próbowałem uzyskać dostęp do jego wartości, wystąpił błąd. Czemu?

+6

Podczas zadawania pytań o budowę błędy, proszę podać rzeczywisty błąd (w całości, kompletny, bez edycji, kopia wklejone jako tekst) w organizmie zapytania. –

+1

Oh sorry. Powoduje błąd w czasie wykonywania. –

+2

"xvalue, więc to życie jest przedłużone" byłoby błędem. C++ wydłuża czas życia * tymczasowych *, a nie wartości l, wartości i wartości. Czyni to, gdy odniesienie jest związane z takim obiektem tymczasowym. W wyrażeniu nie ma obiektu tymczasowego. Co więcej, 'bar' i' baz' zarówno wywołują niezdefiniowane zachowanie, jeden zwracając odwołanie do lokalnego obiektu, jak i drugi, nie zwracając niczego. –

Odpowiedz

18

Myślę, że wartość zwracana baz() byłaby xvalue, więc jego żywotność jest przedłużona.

Na początku to, co zwraca baz() jest zawsze zwisającym odnośnikiem.

Dla int&& baz() { return 10; }, lifetime of the temporary nie jest przedłużony. Jest on wbudowany wewnątrz funkcji i zostanie zniszczony po wyjściu z funkcji, a następnie baz() zawsze zwraca zwisające odwołanie.

tymczasowa granica do wartości zwracanej przez funkcję w return oświadczenie nie jest rozszerzony: to jest niszczone natychmiast po zakończeniu ekspresji powrotnej. Taka funkcja zawsze zwraca zwisające odwołanie.

Następnie dla int&& rr5 = baz();, rr5 jest także zwisającym odnośnikiem; szacunek na to prowadzi do UB i wszystko jest możliwe.

Z drugiej strony, jeśli zmienisz baz() na wartość zwracaną, wszystko byłoby w porządku; wartość zwracana jest kopiowana, a następnie przypisywana do rr5, a czas życia tymczasowego jest przedłużany do czasu życia rr5.

LIVE

+0

Czy nie powinien być zapisany w 'rr5', zanim tymczasowy plik zostanie zniszczony? – CinCout

+1

@CinCout Musiałby być 'przeniesiony' w funkcji' baz() 'aby to zrobić –

+3

@CinCout -' rr5' nie przechowuje niczego. Jest związany z obiektem. Obiekt ten jest w zasadzie zniszczony, zanim nawet wiązanie się stanie. – StoryTeller

Powiązane problemy