Betrachten Sie das folgende Code-Snipet:
%Vor%Ausgabe :
%Vor% i.e. Objektlebensdauer erstreckt sich durch Bezugnahme, die in Herbs Artikel
Aber wenn wir nur eine Zeile Code ändern und schreiben:
%Vor%Aufruf von f (2) am bereits zerstörten Objekt:
Ausgabe :
%Vor%Warum ist das passiert? Ist der Rückgabewert von f () keine korrekte Art von "Zeitlichkeit"?
Wenn Sie eine Funktion also schreiben ...
%Vor% ... Sie weisen den Compiler an, ein const S&
zurückzugeben, und Sie übernehmen die Verantwortung dafür, dass das Objekt, auf das verwiesen wird, eine Lebensdauer hat, die für die Verwendung durch den Aufrufer geeignet ist. ("Sicherstellen" kann die Dokumentation der Clientnutzung darstellen, die mit Ihrem Design ordnungsgemäß funktioniert.)
Oft - mit der typischen Trennung von Code in Header und Implementierungsdateien - ist die Implementierung von f(int) const
selbst für aufrufenden Code nicht sichtbar, und in solchen Fällen hat der Compiler keinen Einblick darüber, welche S
eine Referenz haben könnte zurückgegeben werden, noch ob das S
eine temporäre ist oder nicht, so hat es keine Grundlage, auf der zu entscheiden, ob die Lebensdauer verlängert werden muss.
Neben den offensichtlichen Optionen (z. B. dem Vertrauen der Clients, sicheren Code zu schreiben, Rückgabe nach Wert oder intelligentem Zeiger) ist es sinnvoll, über eine obskurere Option zu wissen ...
%Vor% Die &
und &&
unmittelbar vor der Überfüllung der Funktionskörper f
, so dass die &&
Version verwendet wird, wenn *this
beweglich ist, andernfalls wird die &
Version verwendet. Auf diese Weise bindet jemand, der an ein auslaufendes Objekt ein const &
an f(...)
bindet, an eine neue Kopie des Objekts und verlängert die Lebensdauer um den lokalen Verweis const
, während das Objekt nicht ausläuft (noch nicht ) Die const
Referenz bezieht sich auf das Originalobjekt (welches immer noch nicht garantiert ist, solange die Referenz - Vorsicht ist nötig).
Warum ist das passiert? Ist
f()
's Rückgabewert keine korrekte Art von "Zeitlichkeit"?
Richtig, ist es nicht. Dies ist in letzter Zeit ein etwas kontroverses Thema: Die offizielle Definition von "Zeitlichkeit" ist etwas offen.
In den letzten Compilern hat sich die Zeitlichkeit ausgeweitet. Zuerst wurde es nur auf Prvalue-Ausdrücke (nicht "Referenz" -Ausdrücke) angewendet, und Member-Zugriffe ("Punktoperator") auf solche Ausdrücke angewendet. Jetzt gilt es auch für Cast-Ausdrücke und Array-Zugriffe. Sie können zwar eine Verschiebungsoperation als static_cast< T && >( t )
schreiben, wodurch die Temporalität erhalten bleibt, jedoch wird std::move( t )
einfach nicht geschrieben.
Ich arbeite an einer Serie von Vorschlägen um C ++ zu erweitern, damit Ihr Beispiel wie erwartet funktioniert. Es besteht die Möglichkeit, dass die Funktion in C ++ 17 erscheint.