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

Was von fnc() zurückgegeben Lebensdauer von temporären Objekt ist? Ist es Lebenszeit von "ref" oder von temporärer Referenz static_cast (fnc()), die am Ende der Anweisung zerstört wurde?const Verweis auf temporäre Referenz

Ausgabe von gcc (Lebensdauer von FNC() ist Lebensdauer "ref"):

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

Ausgabe von VS2013 (Lebensdauer von FNC() ist Lebensdauer von temporärer Referenz):

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

Was ist korrekt von Standard?

+0

möglich Duplikat [garantierte Lebensdauer von temporären in C++?] (Http://stackoverflow.com/questions/584824/guaranteed-lifetime-of-temporary-in-c) –

+0

Nur frage mich, was passiert, wenn Sie entferne die 'static_cast <>'? Ich würde erwarten, dass sich beide dann genauso verhalten, nur für den Fall, dass Sie ein echtes Problem haben, das Sie lösen wollen. Wie interpretieren Sie den Standard zu diesem Thema? –

+1

@UlrichEckhardt Der 'static_cast' macht hier den Unterschied. Ohne es wird die Lebensdauer von 'fnc()' garantiert auf 'ref' erweitert. – Angew

Antwort

5

Ich glaube, Visual Studio hier richtig ist, dies in defect report #1376 bedeckt ist, die sagt:

In einer Erklärung wie

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

es nicht klar ist, was die Lebensdauer des T vorübergehend sein sollte . Gemäß Abschnitt 5.2.9 [expr.static.cast] Absatz 4 entspricht der Ausdruck static_cast einer Deklaration einer erfundenen temporären Variablen t. Die Lebensdauer des Temporären wird auf die von t erweitert, aber es ist nicht klar, was diese Lebensdauer sein sollte, noch ob die nachfolgende Bindung von t an r die Lebensdauer des ursprünglichen temporären beeinflussen würde. (Siehe auch Ausgabe 1568.)

und die Diskussion umfasst diese Schlussfolgerung:

Der Verweis auf das xValue Ergebnis der static_cast gebunden ist, so dass die Lebensdauer der temporären nicht verlängert wird und dieses Beispiel führt zu einer freien Referenz.

und defect report 1568 deckt diesen Fall genauer gesagt:

Nach 12,2 [class.temporary] Absätze 4-5,

Es gibt zwei Kontexte, in denen Provisorien bei einem zerstört anderer Punkt als das Ende des vollständigen Ausdrucks ...

Der zweite Kontext ist, wenn eine Referenz an ein temporäres gebunden ist. Die vorübergehende, auf denen die Referenz gebunden ist oder die temporäre, die das komplette Objekt eines subobject der Verweis auf denen gebunden für die gesamte Lebensdauer der Referenz bleibt ...

Es ist nicht klar, ob dies gilt auf ein Beispiel wie folgt aus:

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

und die Antwort war:

Dieses Problem a du ist Problem der Ausgabe 1376.

so in diesem Fall:

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

der Hinweis auf das Ergebnis der static_cast gebunden ist und nicht an CL und deshalb ist eine CL dangling Referenz.

Zur Bezugnahme ist der entsprechende Text aus dem Entwurf der C++ 11 Standard-Teil 5.2.9[expr.static.cast]:

Andernfalls kann ein Ausdruck e explizit auf einen Typ T umgewandelt werden, unter Verwendung von a static_cast des Formulars static_- cast (e) wenn die Deklaration T t (e); ist für einige erfundene temporäre Variable t (8.5) wohlgeformt. Der Effekt einer solchen expliziten Konvertierung entspricht dem Ausführen der Deklaration und Initialisierung und dann Verwenden der temporären Variable als Ergebnis der Konvertierung. Der Ausdruck e wird nur dann als glvalue if und verwendet, wenn die Initialisierung ihn als glvalue verwendet.