Antworten:
Es ist sicher. Const ref verlängert die Lebensdauer von temporären. Der Geltungsbereich ist der Geltungsbereich von const ref.
Die Lebensdauer eines temporären Objekt kann durch Bindung an eine const lvalue Referenz oder auf eine R - Wert - Referenz (da C ++ 11) verlängert werden, siehe Bezug Initialisierung für weitere Einzelheiten.
Immer wenn eine Referenz an ein temporäres Objekt oder an ein Unterobjekt davon gebunden ist, wird die Lebensdauer des temporären Objekts mit den folgenden Ausnahmen verlängert, um der Lebensdauer der Referenz zu entsprechen :
- Eine temporäre Bindung an einen Rückgabewert einer Funktion in einer return-Anweisung wird nicht erweitert: Sie wird sofort am Ende des return-Ausdrucks zerstört. Eine solche Funktion gibt immer eine baumelnde Referenz zurück.
- Eine temporäre Bindung an ein Referenzelement in einer Konstruktorinitialisiererliste bleibt nur so lange bestehen, bis der Konstruktor beendet wird, nicht solange das Objekt vorhanden ist. (Hinweis: Eine solche Initialisierung ist ab DR 1696 schlecht ausgebildet.)
- Eine temporäre Bindung an einen Referenzparameter in einem Funktionsaufruf besteht bis zum Ende des vollständigen Ausdrucks, der diesen Funktionsaufruf enthält: Wenn die Funktion eine Referenz zurückgibt, die den vollständigen Ausdruck überlebt, wird sie zu einer baumelnden Referenz.
- Eine temporäre Bindung an eine Referenz im Initialisierer, die in einem neuen Ausdruck verwendet wird, ist bis zum Ende des vollständigen Ausdrucks vorhanden, der diesen neuen Ausdruck enthält, nicht solange das initialisierte Objekt. Wenn das initialisierte Objekt den vollständigen Ausdruck überlebt, wird sein Referenzelement zu einer baumelnden Referenz.
- Bis zum Ende des vollständigen Ausdrucks, der den Initialisierer enthält, ist eine temporäre Bindung an eine Referenz in einem Referenzelement eines Aggregats vorhanden, das mit der Direktinitialisierungssyntax (Klammern) im Gegensatz zur Listeninitialisierungssyntax (geschweifte Klammern) initialisiert wurde.
struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference
Im Allgemeinen kann die Lebensdauer eines Temporärs nicht durch "Weitergabe" weiter verlängert werden: Eine zweite Referenz, die aus dem Verweis initialisiert wurde, an den das Temporär gebunden war, hat keinen Einfluss auf seine Lebensdauer.
wie @Konrad Rudolph betonte (und siehe den letzten Absatz von oben):
"Wenn
c.GetSomeVariable()
eine Referenz auf ein lokales Objekt oder eine Referenz zurückgegeben wird, die selbst die Lebensdauer eines Objekts verlängert, wird die Lebensdauerverlängerung nicht aktiviert."
c.GetSomeVariable()
eine Referenz auf ein lokales Objekt oder eine Referenz zurückgegeben wird, die selbst die Lebensdauer eines Objekts verlängert, wird die Lebensdauerverlängerung nicht
Dank der Verlängerung der Lebensdauer sollte hier kein Problem auftreten . Das neu erstellte Objekt bleibt bestehen, bis die Referenz den Gültigkeitsbereich verlässt.
Ja, das ist absolut sicher: Die Bindung an eine const
Referenz verlängert die Lebensdauer der temporären Referenz auf den Umfang dieser Referenz.
Beachten Sie, dass das Verhalten jedoch nicht transitiv ist . Zum Beispiel mit
const auto& cc = []{
const auto& c = SomeClass{};
return c;
}();
cc
baumelt.
Das ist sicher.
[class.temporary]/5
: Es gibt drei Kontexte, in denen Provisorien an einem anderen Punkt als am Ende des vollständigen Ausdrucks zerstört werden . [..]
[class.temporary]/6
: Der dritte Kontext ist, wenn eine Referenz an ein temporäres Objekt gebunden ist. Das temporäre Objekt, an das die Referenz gebunden ist, oder das temporäre Objekt, das das vollständige Objekt eines Unterobjekts ist, an das die Referenz gebunden ist, bleibt für die Lebensdauer der Referenz bestehen, wenn der Wert, an den die Referenz gebunden ist, durch eine der folgenden Methoden erhalten wurde : [viele Dinge hier]
In diesem speziellen Fall ist es sicher. Beachten Sie jedoch, dass nicht alle Provisorien sicher durch konstante Referenz erfasst werden können ... zum Beispiel
#include <stdio.h>
struct Foo {
int member;
Foo() : member(0) {
printf("Constructor\n");
}
~Foo() {
printf("Destructor\n");
}
const Foo& method() const {
return *this;
}
};
int main() {
{
const Foo& x = Foo{}; // safe
printf("here!\n");
}
{
const int& y = Foo{}.member; // safe too (special rule for this)
printf("here (2)!\n");
}
{
const Foo& z = Foo{}.method(); // NOT safe
printf("here (3)!\n");
}
return 0;
}
Die für erhaltene Referenz z
ist NICHT sicher zu verwenden, da die temporäre Instanz am Ende des vollständigen Ausdrucks zerstört wird, bevor die printf
Anweisung erreicht wird. Ausgabe ist:
Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!