2017-01-27 2 views
2

Könnte jemand erklären, einfach den Grund, warum dies nicht funktioniert:gemeinsamen Zeiger und Rohzeiger Lebensdauer

std::shared_pointer<Bar> getSharedPointer() { 
    return std::make_shared<Bar>(); 
} 

... 

auto foo = getSharedPointer().get(); 

Offenbar foo den Rohzeiger verwendet, wird eine segfault verursachen, da die Lebensdauer des gemeinsamen Zeiger von getSharedPointer() zurückgegeben wird leerlaufen. Irgendwie würde ich erwarten, dass es bis zum Ende seines Geltungsbereichs (wie auch immer der Block in ihm) dauert.

Ist das korrekt und gibt es analoge Beispiele für diese Situation?

+1

nicht 'getSharedPointer' in der Standardbibliothek oder gemeinsame Dritte dokumentiert gefunden. Keine Ahnung, was passiert. Empfehlen Sie, ein bisschen mehr Informationen hinzuzufügen. – user4581301

Antwort

7

Für getSharedPointer().get(); gibt getSharedPointer() einen temporären std::shared_ptr zurück, der nach dem Ausdruck sofort zerstört wird, und der von ihm verwaltete Zeiger wird ebenfalls gelöscht. Danach wird foo baumeln, jede Dereferenzierung verursacht UB.

auto foo = getSharedPointer().get(); 
// foo have become dangled from here 

Sie könnten eine benannte Variable statt:

auto spb = getSharedPointer(); 
auto foo = spb.get(); 
// It's fine to use foo now, but still need to note its lifetime 
// because spb will be destroyed when get out of its scope 
// and the pointer being managed will be deleted too 
+0

Bitte fügen Sie eine Notiz hinzu, dass 'spb' nur bis zum Ende des Bereichs –

1
auto foo = getSharedPointer().get(); 

Jedes Mal, wenn eine Funktion einen Typ zurückgibt, die keine Referenz ist, ist das Ergebnis der Aufruf der Funktion ein R-Wert. Da die Funktion getSharedPointer() einen Klassentyp zurückgibt, ist das Ergebnis ein temporäres Objekt.

Die Lebensdauer dieses temporären Objekts ist definiert als das Ende der Auswertung des äußersten Ausdrucks, hier getSharedPointer().get(). Sobald die foo Variable initialisiert wird, wird der besitzende Smart Pointer zerstört; Wenn das letzte shared_ptr Besitzer dieses Objekts zerstört wird, wird das Objekt gelöscht.

Hier getSharedPointer() immer wieder shared_ptr, die nicht das verwaltete Objekt nicht teilt (use_count() 1), so dass, wenn die Kopie der letzten shared_ptr zerstört wird, wird das Objekt zerstört und der Zeiger auf das Objekt ist ungültig.

(Ich bin nicht sicher, warum Sie ein shared_ptr zurückkehren und keine unique_ptr hier.)

Die richtige Verwendung eines Smart-Pointer, oder jede Klasse, die „Eigentümer“ andere Ressourcen (die Lebensdauer der Kontrollen) (Ressourcen, auf die Sie immer noch direkt zugreifen dürfen, ist es, den "intelligenten" Zeiger/Eigentümer so lange am Leben zu halten, wie Sie auf die Ressource zugreifen müssen.

So muss der "intelligente" Zeiger (Eigentümerobjekt) benannt werden. Außerdem bin ich mir nicht sicher, ob Sie wirklich die Tatsache verbergen möchten, dass es sich um einen intelligenten Zeiger aus der Sicht des Lesers mit auto handelt.

std::shared_pointer<Bar> foo = getSharedPointer(); 
// use foo.get() 

Möglicherweise möchten Sie die genaue Art der verwalteten Objekt verstecken:

std::shared_pointer<auto> foo = getSharedPointer(); 
+0

reicht. Ich muss mich erneut auf den Code beziehen, um zu sehen, ob ein eindeutiges PTR in der App sinnvoller ist, aber danke für die Köpfe; Ich werde das überprüfen. Außerdem erklärten Sie mir genau, was ich über temporäre Objekte und Lebenszeiten wissen musste, die es mir nicht erlaubten, mich darüber zu informieren, dass ich neu bei cpp bin. Vielen Dank. – tau

Verwandte Themen