Frage

Warum tut dies:

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

Geben Sie Ausgang:

Die Antwort lautet:

Statt:

Die Antwort lautet: vier

War es hilfreich?

Lösung

Nur local const Referenzen verlängern die Lebensdauer.

Die Norm legt ein solches Verhalten in §8.5.3 / 5, [dcl.init.ref], der Abschnitt über Initialisierungen von Referenz Erklärungen. Der Verweis in Ihrem Beispiel wird an den Konstruktor Argumente n gebunden, und ungültig wird, wenn das Objekt n an geht gebunden ist von Umfang aus.

Die Laufzeitverlängerung ist durch ein Funktionsargument nicht transitiv. Kapitel 12.2 / 5 [class.temporary]:

Der zweite Kontext ist, wenn eine Referenz auf ein temporäres gebunden ist. Die temporär, an der das Referenz gebunden ist oder die temporäre, dass das komplette Objekt zu einem Subobjekt ist, von denen die temporären Ausnahme gebundene bleibt für die gesamte Lebensdauer der Referenz ist, wie unten angegeben. Eine temporäre gebunden an ein Referenzelement in einem Konstruktor des Ctor-Initialisierer (§12.6.2 [class.base.init]) bleibt bestehen, bis der Konstruktor beendet. Eine temporäre gebunden an einen Referenzparameters in einem Funktionsaufruf (§5.2.2 [expr.call]) besteht, bis die Vollendung des vollen Ausdruck den Anruf enthält.

Andere Tipps

Hier ist die einfachste Art und Weise zu erklären, was passiert ist:

In main () erstellt man einen String und übergeben es an den Konstruktor. Diese String-Instanz nur im Konstruktor existiert. Innerhalb Konstruktor Sie Mitglied zugewiesen direkt an diese Instanz zu verweisen. Wenn beim Umfang den Konstruktor links wurde die String-Instanz zerstört und Mitglied dann zu einem String-Objekt darauf hingewiesen, dass nicht mehr existierte. Sandbox.member Punkt auf eine Referenz außerhalb ihres Umfang hat, wird nicht diese externen Instanzen in ihrem Umfang halten.

Wenn Sie Ihr Programm korrigieren möchten das Verhalten anzuzeigen, die Sie wünschen, die folgenden Änderungen vor:

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}

Nun Temperatur wird am Ende des Haupt Spielraum umkippen () statt am Ende des Konstrukteurs. Dies ist jedoch eine schlechte Praxis. Ihre Membervariablen sollten nie ein Verweis auf eine Variable sein, die außerhalb der Instanz existiert. In der Praxis, die Sie nie wissen, wann die Variable Umfang hinausgehen wird.

Was ich empfehlen ist Sandbox.member als const string member; zu definieren Dies wird die temporäre Parameterdaten in die Membervariable statt Zuweisen der Membervariable als temporäre Parameter kopiert sich.

Technisch gesehen, ist dieses Programm nicht tatsächlich ausgegeben etwas auf der Standardausgabe erforderlich ist (die ein gepufferte Strom ist für den Anfang).

  • Das cout << "The answer is: " Bit wird emittieren "The answer is: " in die Puffer von stdout.

  • Dann wird das << sandbox.member Bit die baumelnden Referenz in operator << (ostream &, const std::string &) liefern, die Invokes nicht definiertes Verhalten .

Aus diesem Grund, wird nichts passieren garantiert. Das Programm kann scheinbar gut funktionieren oder sogar ohne Spülung stdout abstürzen - was bedeutet, den Text „Die Antwort lautet:“. Nicht auf dem Bildschirm angezeigt bekommen

Weil Ihre temporären String ging der Umfang, sobald der Sandbox Konstruktor zurückgegeben, und der Stapel besetzt, indem sie es für einige andere Zwecke zurückgewonnen wurde.

Im Allgemeinen sollten Sie nie Referenzen langfristige halten. Referenzen sind gut für die Argumente oder lokale Variablen, niemals die Teilnehmer.

you're referring to something which has vanished. The following will work

#include <string>
#include <iostream>

class Sandbox
{

public:
    const string member = " "; //default to whatever is the requirement
    Sandbox(const string& n) : member(n) {}//a copy is made

};

int main()
{
    Sandbox sandbox(string("four"));
    std::cout << "The answer is: " << sandbox.member << std::endl;
    return 0;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top