Können C ++ 11 unique_ptr und shared_ptr in den Typ des anderen konvertieren?

99

Bietet die C ++ 11-Standardbibliothek ein Dienstprogramm zum Konvertieren von a std::shared_ptrnach std::unique_ptroder umgekehrt? Ist das ein sicherer Betrieb?

Hinterforsum
quelle
Definieren Sie bitte "sicherer Betrieb". Welche Art von Sicherheit suchen Sie? Lebenszeitmanagementsicherheit? Gewindesicherheit?
jaggedSpire
2
"STL" bedeutet nicht Standardbibliothek. Die STL hat nichts damit zu tun shared_ptr.
Neugieriger
1
@jaggedSpire Thread-Sicherheit würde bedeuten, dass Sie Besitzer haben, die in verschiedenen Threads verwendet werden, dh die Anzahl der Verwendungen ist nicht 1.
neugieriger Kerl
@curiousguy Das wusste ich. Mein Punkt war, dass "Sicherheit" in der Frage von OP nicht genau definiert war, und er musste klären, welche Art von "Sicherheit" er meinte, da es mehrere Arten gibt.
jaggedSpire

Antworten:

161

std::unique_ptrist die C ++ 11-Methode, um exklusives Eigentum auszudrücken. Eine der attraktivsten Funktionen ist jedoch, dass sie einfach und effizient in a konvertiert werden kann std::shared_ptr.

Dies ist ein wesentlicher Grund std::unique_ptrdafür, warum es als Werksfunktionstyp so gut geeignet ist. Factory-Funktionen können nicht wissen, ob Anrufer die Semantik der exklusiven Eigentümerschaft für das zurückgegebene Objekt verwenden möchten oder ob eine gemeinsame Eigentümerschaft (dh std::shared_ptr) besser geeignet wäre. Durch die Rückgabe von a std::unique_ptrbieten Fabriken Anrufern den effizientesten intelligenten Zeiger, aber sie hindern Anrufer nicht daran, ihn durch flexiblere Geschwister zu ersetzen.

std::shared_ptrzu std::unique_ptrist nicht erlaubt. Sobald Sie die lebenslange Verwaltung einer Ressource an eine übergeben haben std::shared_ptr, ändert sich Ihre Meinung nicht mehr. Selbst wenn der Referenzzähler eins ist, können Sie das Eigentum an der Ressource nicht zurückfordern, std::unique_ptrum sie beispielsweise verwalten zu lassen.

Referenz: Effektives modernes C ++. 42 SPEZIFISCHE MÖGLICHKEITEN, IHRE VERWENDUNG VON C ++ 11 UND C ++ 14 ZU VERBESSERN. Scott Meyers.

Kurz gesagt, können Sie einfach und konvertieren ein effizienter std::unique_ptrzu , std::shared_ptraber sie nicht konvertieren kann std::shared_ptrzu std::unique_ptr.

Beispielsweise:

std::unique_ptr<std::string> unique = std::make_unique<std::string>("test");
std::shared_ptr<std::string> shared = std::move(unique);

oder:

std::shared_ptr<std::string> shared = std::make_unique<std::string>("test");
chema989
quelle
9
...Wie machst du das?
Jake
4
@ Jake Ich habe ein Beispiel hinzugefügt
chema989
Beachten Sie, dass während der Compiler (zumindest nicht gcc) erlaubt tatsächlich nicht verhindern (oder sogar warnen) , wenn Sie versehentlich (zB durch den Zeiger Typ einer Membervariable zu ändern) zuordnen std::unique_ptrzu ein std::shared_ptr.
StefanQ
-8

Erstellen Sie mit unique_ptr u_ptr shared_ptr s_ptr:

std::shared_ptr<whatever> s_ptr(u_ptr.release());

In die andere Richtung zu gehen ist unpraktisch.

nmr
quelle
29
Hier ist der "richtige" Weg:std::shared_ptr<whatever> s_ptr(std::move(u_ptr));
Emlai
6
Und hier ist der pedantische "richtige" Weg:std::shared_ptr<whatever> s_ptr{std::move(u_ptr)};
Polyvertex
3
Was ist daran weniger sicher?
nmr
7
@VioletGiraffe • Ich nehme an, Polyvertex empfiehlt die Verwendung der neuen Initialisierungslistensyntax, die stille Verengungskonvertierungen vermeidet und die Elementinitialisierung mit einer einheitlichen Syntax berücksichtigt, als gute Angewohnheit. Sechs von einem, ein halbes Dutzend von dem anderen?
Eljay
8
@nmr Es ist unsicher, weil Sie das Deleterimunique_ptr
Zang MingJie