2015-03-20 15 views
7
#include <iostream> 
using namespace std; 

struct CL 
{ 
    CL() 
    { 
     cout<<"CL()"<<endl; 
    } 
    CL(const CL&) 
    { 
     cout<<"CL(const CL&)"<<endl; 
    } 
    ~CL() 
    { 
     cout<<"~CL()"<<endl; 
    } 
}; 

CL cl; 

CL fnc() 
{ 
    return cl; 
} 

int main() { 
    cout<<"start"<<endl; 
    const CL& ref=static_cast<const CL&>(fnc()); 
    //...Is "ref" valid here?? 
    cout<<"end"<<endl; 
    return 0; 
} 

Co to jest czas życia tymczasowego obiektu zwróconego przez fnc()? Czy jest to okres istnienia "ref" lub tymczasowego odniesienia static_cast (fnc()), który został zniszczony na końcu instrukcji?const odniesienie do tymczasowego odniesienia

Wyjście gcc (żywotność FNC() jest żywotność "ref"):

CL() //global object "cl" 
start 
CL(const CL&) 
end 
~CL() 
~CL() //global object "cl" 

Wyjście VS2013 (dożywotnią z FNC() jest żywotność czasowego odniesienia):

CL() //global object "cl" 
start 
CL(const CL&) 
~CL() 
end 
~CL() //global object "cl" 

Co jest poprawne według standardu?

+0

możliwe duplikat [Gwarantowanych trwania tymczasowej w C++?] (Http://stackoverflow.com/questions/584824/guaranteed-lifetime-of-temporary-in-c) –

+0

prostu zastanawiasz się, co się dzieje, jeśli usunąć 'static_cast <>'? Spodziewałbym się, że oba będą zachowywały się tak samo wtedy, na wypadek, gdybyś miał prawdziwy problem, który chcesz rozwiązać. Jaka jest twoja interpretacja normy dotyczącej tego problemu? –

+1

@UlrichEckhardt "static_cast" to tutaj robi różnicę. Bez tego, czas życia 'fnc()' ma być rozszerzony na czas trwania 'ref'. – Angew

Odpowiedz

5

wierzę Visual Studio jest tutaj poprawne, to jest pokryta defect report #1376 który mówi:

W deklaracji jak

T&& r = static_cast<T&&>(T()); 

nie jest jasne, co żywotność T tymczasowa powinna być . Zgodnie z 5.2.9 [expr.static.cast] paragraf 4, static_cast jest równoznaczne z deklaracją wymyślonej zmiennej tymczasowej t. Czas życia tymczasowego jest przedłużony do czasu t, ale nie jest jasne, jaki powinien być ten czas życia, ani też, czy późniejsze powiązanie z wartością t wpłynęłoby na czas życia oryginalnego tymczasowego. (Patrz również problem 1568)

i dyskusja włącza ten wniosek:

Wniosek jest zobowiązany do wyniku xvalue z static_cast, więc cały okres przejściowy nie zostanie przedłużony, a to przykład daje odwołanie do danglingu.

i defect report 1568 obejmuje ten przypadek dokładniej:

Według 12,2 [class.temporary] punktach 4-5,

Istnieją dwa podejścia, w którym uzupełnienia tymczasowe ulegają zniszczeniu przy A inny punkt niż koniec pełnego wyrażenia ...

Drugi kontekst dotyczy odniesienia do pliku tymczasowego. Tymczasowa, do której odniesienia jest związany lub tymczasowy, który jest pełna przedmiotem podobiektu do których odniesienia związanego utrzymuje się przez cały okres odniesienia ...

Nie jest jasne, czy dotyczy to na przykład tak:

struct S { }; 
const S& r = (const S&)S(); 

i odpowiedź brzmiała:

Ten problem jest du numer wersji 1376.

więc w tym przypadku:

const CL& ref=static_cast<const CL&>(fnc()); 

odniesienia jest związany z wynikiem static_cast a nie do CL a zatem CL jest zwisające odniesienia.

Dla porównania odpowiedni tekst z projektu C++ 11 część standardowa 5.2.9[expr.static.cast]:

W przeciwnym przypadku ekspresji E można bezpośrednio przekształcić do typu T za pomocą static_cast formularza static_- cast (e) jeśli deklaracja T t (e); jest dobrze ukształtowany, dla pewnej wymyślonej zmiennej tymczasowej t (8.5). Efekt takiej jawnej konwersji jest taki sam, jak wykonanie deklaracji i inicjalizacji, a następnie użycie zmiennej tymczasowej w wyniku konwersji. Wyrażenie e jest używane jako wartość glina if i tylko wtedy, gdy inicjalizacja używa go jako wartości gl.

Powiązane problemy