2013-03-20 9 views
5

Auch wenn das Thema wurde hier oft diskutiert, kann ich keine schlüssige Erklärung zu meinem speziellen Fall finden. Will const die Lebensdauer des RefTest vorübergehend verlängern? Ist das folgende Beispiel legal?Const Referenz als Klassenmitglied

#include <iostream> 

class RefTest 
{ 
public: 
    RefTest(const std::string &input) : str(input) {} 
    ~RefTest() {std::cout << "RefTest" << std::endl;} 
private: 
    std::string str; 
}; 

class Child 
{ 
public: 
    Child (const RefTest &ref) : ref_m(ref) {} 
    ~Child() {std::cout << "Test" << std::endl;} 
private: 
    const RefTest &ref_m; 
}; 

class Test 
{ 
public: 
    Test() : child(RefTest("child")) {}//Will the temporary get destroyed here? 
    ~Test() {std::cout << "Test" << std::endl;} 
private: 
    const Child child; 
}; 

int main() 
{ 
    Test test; 
} 
+5

Das letzte Zeile kein Objekt schafft überhaupt . Es erklärt eine Funktion. Siehe http://en.wikipedia.org/wiki/Most_vexing_parse. –

+0

@OliCharlesworth Oh, schießen. Ich fürchtete, das Beispiel ist dumm :(Bitte sehen Sie meine aktualisierte, die ein bisschen näher an meiner realen Situation sein sollte. Dieses Mal, ich glaube nicht, dass es irgendwelche ärgerlichen Parse-Probleme geben sollte. –

+0

@NayanaAdassuriya die 'test2 '? Ich hatte mein anfängliches Beispiel umgeschrieben, weil ich nicht genug darüber nachgedacht habe. –

Antwort

5

Die Referenz tut nicht die Lebensdauer verlängern. Der Code ist zulässig, aber nur, weil Sie nach Abschluss des Konstruktors nie auf ref_m zugreifen.

Das temporäre Objekt ist an den Konstruktorparameter ref gebunden. Das Binden eines weiteren Verweises später, ref_m, verlängert die Lebensdauer nicht. Wenn dies der Fall wäre, hätten Sie ein Objekt auf dem Stapel, das so lange bestehen bleiben muss, wie das Referenzelement, an das es gebunden ist, dem Heap zugeordnet werden könnte. Der Compiler kann den Stapel also nicht wieder auflösen, wenn der Konstruktor zurückkehrt.

Es wäre nett, eine Warnung zu erhalten, aber Compiler sind nicht perfekt und einige Dinge sind schwer zu warnen. Das Temporäre wird in einem anderen Kontext erstellt, als dort, wo es an eine Referenz gebunden ist. Der Compiler kann also nur feststellen, ob ein Problem mit aktiviertem Inlinging oder einer cleveren statischen Analyse vorliegt.

+0

Oh, verdammt nochmal, mir ist nicht in den Sinn gekommen, dass es sich daran bindet der Funktionsparameter, und nicht das interne Element. Danke, dass Sie darauf hingewiesen haben. –

+0

Auch wenn Sie im Child-Konstruktor ein temporäres Beispiel erstellen, zB 'ref_m (RefTest (" "))' dann verlängert es nicht die Lebensdauer nach dem Ende des Konstruktors, aus dem gleichen Grund, dass Das Temporäre befindet sich im Stack-Frame des Konstruktors und muss zerstört werden, wenn diese Funktion zurückkehrt. Der Standard besagt explizit: "Eine temporäre Bindung an ein Referenzelement im Konstruktor ctor-initializer (12.6.2) bleibt bestehen, bis der Konstruktor beendet wird." 12.2 [class.temporary] –

+0

In der Tat.Dann sind die meisten Antworten, die ich hier gesehen habe, irreführend. Ich hatte den Eindruck, dass, wenn ich einer ** const ** -Referenz ein Temporäres zuweisen würde, das Objekt erst dann zerstört würde, wenn die Referenz den Gültigkeitsbereich verlässt und nicht das Temporäre selbst. –

3

Die C++ Standard Zustände:

Der zweite Rahmen ist, wenn eine Referenz auf ein temporäres gebunden ist. Das Temporäre, an das der Verweis gebunden ist, oder das temporäre Objekt , das an ein Unterobjekt gebunden ist, an das das temporäre gebunden ist, bleibt für die gesamte Lebensdauer des Verweises bestehen, mit Ausnahme der unten angegebenen Ausnahmen. Eine temporäre Bindung an ein Referenzelement in einem Konstruktor ctor-Initialisierer (12.6.2) bleibt bestehen, bis der Konstruktor beendet wird. Eine temporäre Bindung an einen Referenzparameter in einem Funktionsaufruf (5.2.2) bleibt bestehen bis zum Abschluss des vollständigen Ausdrucks, der den Aufruf enthält.

HINWEIS: Und übrigens, ist diese doppelte (1, 2), sollten Sie besser, das nächste Mal suchen ... :)

+0

Ja, jetzt ist es klar. Danke für das Zitat aus dem Standard. –

+0

Danke für die Referenzen in der Bearbeitung. Es gibt zu viele Fragen zu diesem Thema hier und jetzt kann ich verstehen, warum ... Die meisten von ihnen haben mir den Eindruck vermittelt, dass die Zuweisung eines Temporären an eine Const-Referenz ihr Leben verlängern wird, bis die Referenz außer Reichweite ist. –

Verwandte Themen