2013-03-14 13 views
7

Czy ktoś może sprawdzić, czy jest to BŁĄD i wyjaśnić, dlaczego? Myślę, że wiem, ale nie jestem pewien szczegółów. (Mój rzeczywisty problem zaangażowanych wektor teksty stałe, a nie wskazówki, ale nie sądzę, powinna ona znaczenia.) Załóżmy, że mam następujący kod:Odniesienie do elementu wektora zwrócony przez funkcję w C++

std::vector<int> f (void) { 
    std::vector<int> v; 
    v.push_back(5); 
    return v; 
} 

void g (void) { 
    const int &myIntRef = f()[0]; 
    std::cout << myIntRef << std::endl; 
} 

mam rację, że myIntRef jest natychmiast wiszącym odniesienia, ponieważ zwracana wartość f jest zapisana nigdzie na stosie?

Czy poprawka jest poprawna, czy nadal jest błędem?

const int myIntCopy = f()[0]; // copy, not a reference 

Innymi słowy, czy wynik powrotu f() wyrzucony przed skopiowaniem 0 elementu?

+0

Jestem po prostu ciekawy, ale czy istnieje jakikolwiek powód, aby użyć 'int const &' zamiast 'int' jako zmiennej lokalnej? –

+0

@JamesKanze: Może oznaczyć zmienną jako "const"? –

Odpowiedz

2

Tak, rzeczywiście jest to złe. Podczas rozmowy telefonicznej:

return v; 

tymczasowa kopia obiektu v jest tworzony i

const int &myIntRef = f()[0]; 

inicjuje swoje odniesienia z pierwszego elementu tej tymczasowej kopii. Po tym wierszu kopia tymczasowa już nie istnieje, co oznacza, że ​​myIntRef jest nieprawidłową referencją, której użycie powoduje nieokreślone zachowanie nieokreślone zachowanie.

Co należy zrobić, to:

std::vector<int> myVector = f(); 
const int &myIntRef = myVector[0]; 
std::cout << myIntRef << std::endl; 

który (dzięki kopia elizja) wykorzystuje operator przypisania zainicjować myVector obiekt za pomocą v bez kopii v tworzone. W tym przypadku czas życia twojego odniesienia jest równy czasowi życia obiektu myVector, dzięki czemu jest to całkowicie poprawny kod.


I drugie pytanie: "Ponadto, jest następujący ważny dylemat, czy jest to nadal bug"

const int myIntCopy = f()[0]; // copy, not a reference 

Tak, jest to kolejna z możliwych rozwiązań. f()[0] uzyska dostęp do pierwszego elementu tymczasowej kopii i użyje jej wartości do zainicjowania zmiennej myIntCopy.To jest zagwarantowane, że kopia v zwrócony przez f() istnieje przynajmniej dopóki całe wyrażenie jest wykonywane, zobacz C++ 03 Standardowe 12,2 obiektów tymczasowych §3:

obiekty tymczasowe są niszczone jako ostatni krok w oceniając pełne wyrażenie (1.9), które (leksykalnie) zawiera punkt, w którym zostały utworzone.

+0

Dziękuję bardzo. – user2170028

11

To jest błąd. Pod koniec pełnego wyrażenia const int &myIntRef = f()[0]; tymczasowy wektor zostanie zniszczony, a pamięć zwolniona. Każde późniejsze użycie myIntRef jest niezdefiniowanym zachowaniem.

W niektórych okolicznościach powiązanie odniesienia z tymczasowym może przedłużyć okres ważności tymczasowego. Nie jest to jedna z takich sytuacji, kompilator nie wie, czy odwołanie zwracane przez std::vector<int>::operator[] jest częścią tymczasowego odwołania lub odniesienia do int ze statycznym czasem przechowywania lub jakąkolwiek inną rzeczą i nie wydłuży czasu życia.

+0

Świetnie - wielkie dzięki. – user2170028

+0

Przy okazji dodałem kolejne pytanie, jeśli czujesz się tak pochłonięty :-). – user2170028

+0

@ user2170028: Odpowiedz na pytanie uzupełniające: Tak. Zobacz moją odpowiedź :) – LihO

Powiązane problemy