C ++ 11 unique_ptr e shared_ptr sono in grado di convertirsi l'uno nel tipo dell'altro?


99

La libreria standard C ++ 11 fornisce un'utilità per convertire da std::shared_ptra std::unique_ptro viceversa? Questa operazione è sicura?


Definisci "operazione sicura" per favore. Che tipo di sicurezza stai cercando? sicurezza nella gestione della vita? Sicurezza del filo?
jaggedSpire

2
"STL" non significa libreria standard. Il STL non ha nulla a che fare con shared_ptr.
curioso

1
@jaggedSpire La sicurezza dei thread significherebbe che i proprietari sono utilizzati in thread diversi, ovvero il conteggio degli utilizzi non è 1.
curioso

@curiousguy lo sapevo. Il mio punto era che la "sicurezza" non era ben definita nella domanda di OP, e aveva bisogno di chiarire quale tipo di "sicurezza" intendeva poiché ce ne sono più tipi.
jaggedSpire

Risposte:


161

std::unique_ptrè il modo in C ++ 11 per esprimere la proprietà esclusiva, ma una delle sue caratteristiche più interessanti è che si converte facilmente ed efficacemente in un file std::shared_ptr.

Questa è una parte fondamentale del motivo per cui std::unique_ptrè così adatto come tipo di ritorno di una funzione di fabbrica. Le funzioni di fabbrica non possono sapere se i chiamanti vorranno utilizzare la semantica della proprietà esclusiva per l'oggetto che restituiscono o se la proprietà condivisa (cioè std::shared_ptr) sarebbe più appropriata. Restituendo a std::unique_ptr, le factory forniscono ai chiamanti il ​​puntatore intelligente più efficiente, ma non impediscono ai chiamanti di sostituirlo con il suo fratello più flessibile.

std::shared_ptra std::unique_ptrnon è consentito. Una volta che hai trasformato la gestione della vita di una risorsa in una std::shared_ptr, non puoi cambiare idea. Anche se il conteggio dei riferimenti è uno, non puoi rivendicare la proprietà della risorsa per, ad esempio, std::unique_ptrgestirla.

Riferimento: Effective Modern C ++. 42 MODI SPECIFICI PER MIGLIORARE L'UTILIZZO DI C ++ 11 E C ++ 14. Scott Meyers.

In breve, puoi convertire facilmente ed efficientemente un std::unique_ptra in std::shared_ptrma non puoi convertirlo std::shared_ptrin std::unique_ptr.

Per esempio:

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

o:

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

9
...Come si fa?
Jake

4
@ Jake ho aggiunto un esempio
chema989

Tieni presente che, sebbene non sia consentito, il compilatore (almeno non gcc) in realtà non impedirà (o addirittura avviserà) se accidentalmente (ad esempio cambiando il tipo di puntatore di una variabile membro) assegni a std::unique_ptra a std::shared_ptr.
StefanQ,

-8

Dato unique_ptr u_ptr, crea shared_ptr s_ptr:

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

Andare dall'altra parte non è pratico.


29
Ecco il modo "giusto":std::shared_ptr<whatever> s_ptr(std::move(u_ptr));
emlai

6
Ed ecco la pedante via "giusta":std::shared_ptr<whatever> s_ptr{std::move(u_ptr)};
polyvertex

3
Cosa c'è di meno sicuro?
nmr

7
@VioletGiraffe • Suppongo che Polyvertex stia sostenendo l'uso della nuova sintassi dell'elenco di inizializzazione - che evita conversioni di restringimento silenziose e consente l'inizializzazione dei membri con una sintassi uniforme - come una buona abitudine per entrare. Sei su uno, mezza dozzina dell'altro?
Eljay

8
@nmr Non è sicuro perché potresti perdere il contenuto Deleterall'interno diunique_ptr
Zang MingJie
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.