2016-02-12 9 views
6

Zastanawiam się, dlaczego zwrócenie const reference obiektu lokalnego jest nielegalne, a zwrócenie numeru local object jest zgodne z prawem, o ile zostało przypisane do const reference?return const reference a tymczasowy obiekt

vector<int> f_legal() { 
    vector<int> tempVec; 
    tempVec.push_back(1); 
    return tempVec; 
} 

const vector<int>& f_illegal() { 
    vector<int> tempVec; 
    tempVec.push_back(1); 
    return tempVec; 
} 

void g() { 
    const vector<int>& v1 = f_legal(); // legal 
    const vector<int>& v2 = f_illegal(); // illegal 
} 

Edit: Chodzi mi o to, że jeśli przypisanie const ref do zwracanej zmiennej lokalnej jest legalne, to nie powinno przypisanie const ref do zwracanego const ref zmiennej lokalnej być legalne, jak również?

+2

@Ed Heal Tak, to jest dobrze zdefiniowane w C++, że odwołanie do stałej lokalnej wydłuży czas życia tymczasowego, z którym jest związany. –

+2

@EdHeal tak, to jest legalne. W standardzie istnieje specjalny przypadek, który utrzyma obiekt lokalny przy życiu, o ile istnieje odniesienie do niego w bieżącym zakresie. –

Odpowiedz

6

Nawet jeśli przypiszesz go do odwołania const, to zwracana wartość zostanie zadeklarowana jako przekazana przez wartość, co oznacza, że ​​zostanie skopiowana [1] na zewnątrz jako obiekt tymczasowy, a następnie powiązana z odwołaniem do const . Wiązanie obiektu tymczasowego z referencją jest w porządku, obiekt nie zostanie zniszczony, dopóki nie wyjdzie z okresu trwałości odniesienia do stałej.

Z drugiej strony powracanie zmiennej lokalnej jest niepoprawne. Lokalna zmienna zostanie zniszczona po powrocie funkcji, co oznacza, że ​​zewnętrzne odniesienie będzie zwisające.

EDIT

Chodzi mi o to, że jeśli przypisanie const ref do zwracanej zmiennej lokalnej jest legalne, to nie powinno przypisanie const ref do zwracanego const ref zmiennej lokalnej być prawnym jako dobrze?

Punkt jest 1 przypadek nie jest przypisanie const ref do zwracanego zmiennej lokalnej, to przypisanie const ref do zmiennej powrócił tymczasowy. (Który może kopiowane ze zmiennej lokalnej.)


[1] Kopie można pominąć w zależności od RVO technicznie.

+0

Czy na pewno tak jest zawsze? Nawet biorąc pod uwagę "RVO/NRVO"? –

+0

@JamesAdkison: Będzie obiekt tymczasowy, a odwołanie będzie wiązało się z tym tymczasowym. Kopia może zostać usunięta (jeśli wynik może być skonstruowany bezpośrednio w pliku tymczasowym). –

+0

@BenVoigt Tak, to był mój punkt (tzn. Kopia mogła zostać usunięta). –

8

Przywrócenie odwołania do zmiennej lokalnej jest niedozwolone (niezdefiniowane zachowanie). Kropka. Nie ma klauzuli const ani.

Wynika to z faktu, że zmienne lokalne funkcji mają automatyczny czas przechowywania. Są "zniszczone" po wyjściu funkcji. Jeśli funkcja zwraca odniesienie do takiej zmiennej, to odwołanie mówi się, że jest zwisające: odnosi się do obiektu, który już nie istnieje.

Pierwsza z nich jest legalna z powodu specjalnej reguły C++: inicjowanie odwołania do obiektu prvalue wydłuża czas życia tego obiektu tymczasowego do okresu istnienia odwołania.

+0

Reguła właściwie nie ma nic wspólnego z 'const' - każde odniesienie, które jest * bezpośrednio * związane z chwilowym, przedłuża czas życia tego tymczasowego.W C++ 98 inne reguły przewidywały, że tylko odniesienia do stałych mogą bezpośrednio wiązać się z tymczasowym, te reguły zostały teraz zmienione, co miało efekt domina w regule przedłużania życia. –

+0

@BenVoigt To pierwsze, co słyszę o tym. Czy możesz podać referencję? – bolov

+0

Zobacz http://stackoverflow.com/a/3716360/103167 –

1

Najprawdopodobniej całkowicie zrujnowałoby konwencje wywoływania połączeń oparte na stosach, które służyły nam dobrze przez całe dziesięciolecia ... to prawie każdy procesor zakłada.

Powiązane problemy