2015-03-20 13 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; 
} 

Qual è la durata dell'oggetto temporaneo restituito da fnc()? E 'la vita di "ref" o di riferimento temporaneo static_cast (fnc()), che ha distrutto alla fine dell'istruzione?const riferimento a riferimento temporaneo

uscita di gcc (vita di FNC() è la vita di "ref"):

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

uscita di VS2013 (vita di FNC() è la vita di riferimento temporaneo):

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

Che cosa è corretto per Standard?

+0

possibile duplicato del [Durata garantita delle temporanea in C++?] (Http://stackoverflow.com/questions/584824/guaranteed-lifetime-of-temporary-in-c) –

+0

Chiedo solo, cosa succede se si rimuovere il 'static_cast <>'? Mi aspetterei che entrambi si comportino allo stesso modo, nel caso in cui tu abbia un problema reale che vuoi risolvere. Inoltre, qual è la tua interpretazione dello standard riguardante questo problema? –

+1

@UlrichEckhardt Il 'static_cast' è ciò che fa la differenza qui. Senza di esso, la durata di 'fnc()' è garantita per essere estesa a quella di 'ref'. – Angew

risposta

5

Credo Visual Studio è corretto qui, questo è coperto in defect report #1376 che dice:

In una dichiarazione come

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

non è chiaro quale sia la durata del T temporanea dovrebbe essere . In base al paragrafo 4, paragrafo 5 [5], [expr.static.cast], il protocollo statico è equivalente a una dichiarazione di una variabile temporanea inventata t. La durata del temporaneo di è estesa a quella di t, ma non è cancellare quale dovrebbe essere quella durata, né se il successivo legame di t in r influirebbe sulla durata del temporaneo originale. (Vedi anche problema 1568.)

e la discussione include questa conclusione:

Il riferimento è legato al risultato xValue del static_cast, in modo che la durata della temporanea non è esteso e questo esempio si traduce in un riferimento ciondolante.

e defect report 1568 copre questo caso più precisamente:

Secondo 12.2 [class.temporary] paragrafi 4-5,

Ci sono due contesti in cui provvisori vengono distrutti in un punto diverso rispetto alla fine della full-espressione ...

Il secondo contesto è quando un riferimento è legato a un temporaneo. La temporanea in cui il riferimento è associato o la temporanea che è l'oggetto completo di un oggetto secondario a cui è vincolato il riferimento persiste per la durata del riferimento ...

Non è chiaro se questo vale ad esempio come la seguente:

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

e la risposta è stata:

Questo problema è un du plicate of issue 1376.

quindi in questo caso:

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

il riferimento è legato al risultato della static_cast e non CL e quindi CL è un riferimento penzoloni.

Per riferimento relativo testo dal progetto C++ 11 sezione standard 5.2.9[expr.static.cast]:

Altrimenti, un'espressione e può essere esplicitamente convertito in un tipo T utilizzando un static_cast del modulo static_- cast (e) se la dichiarazione T t (e); è ben formato, per qualche variabile temporanea inventata t (8.5). L'effetto di tale conversione esplicita è lo stesso che eseguire la dichiarazione e l'inizializzazione e quindi utilizzando la variabile temporanea come risultato della conversione. L'espressione e viene utilizzata come glvalue if e solo se l'inizializzazione la utilizza come glvalue.

Problemi correlati