Domanda

  

Eventuali duplicati:
   Come liberare puntatore da boost :: shared_ptr?

Una funzione di mia interfaccia restituisce un puntatore ad un oggetto. L'utente dovrebbe assumere la proprietà di tale oggetto. Non voglio tornare un Boost.shared_ptr, perché non voglio forzare i clienti a utilizzare boost. Internamente però, vorrei memorizzare il puntatore in una shared_ptr per evitare perdite di memoria in caso di eccezioni, ecc Non sembra esserci alcun modo per staccare un puntatore da un puntatore condiviso. Tutte le idee qui?

È stato utile?

Soluzione

Quello che stai cercando è una funzione release; shared_ptr non dispone di una funzione di rilascio. Per il manuale di Boost :

  

Q. Perché non shared_ptr fornire una funzione di rilascio ()?

     

A. shared_ptr non può dare via proprietà meno che non sia unico (), perché l'altra copia sarà ancora distruggere l'oggetto.

     

Si consideri:

shared_ptr<int> a(new int);
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2

int * p = a.release();

// Who owns p now? b will still call delete on it in its destructor.
  

Inoltre, il puntatore restituito da release () sarebbe difficile da rilasciare in modo affidabile, come lo shared_ptr fonte potrebbe essere stato creato con un deleter personalizzato.

Due opzioni che si potrebbe prendere in considerazione:

  • Si potrebbe utilizzare std::tr1::shared_ptr, che richiederebbe agli utenti di utilizzare un'implementazione C ++ librerie di supporto TR1 o per utilizzare Boost; almeno questo darebbe loro la possibilità di scegliere tra i due.
  • Si potrebbe implementare il proprio puntatore condiviso boost::shared_ptr-like e l'uso che sulle interfacce esterne.

Si potrebbe anche guardare la discussione a questa domanda sulla usando boost :: shared_ptr nell'interfaccia di una biblioteca pubblica.

Altri suggerimenti

c'è sempre un modo: -)

V'è infatti una ragione per cui essi non forniscono un metodo di rilascio (), ma non è impossibile crearne uno. Fai la tua deleter. Qualcosa sulla linea del (non hanno effettivamente compilato il codice, ma questa è la nozione generale):

template <typename T>
class release_deleter{
public:
  release_deleter() : released_(new some_atomic_bool(false)){}
  void release() {released_->set(true);}
  void operator()(T* ptr){if(!released_->get()) delete ptr;}
private:
  shared_ptr<some_atomic_bool> released_;
}

..

shared_ptr<some_type> ptr(new some_type, release_deleter<some_type>());

..

release_deleter<some_type>* deleter = get_deleter<release_deleter<some_type>>(ptr);
deleter->release();
some_type* released_ptr = ptr.get();
  

L'utente dovrebbe assumere la proprietà di tale oggetto. Non voglio tornare un Boost.shared_ptr,

shared_ptr esprime condiviso di proprietà, e si desidera l'interfaccia per esprimere trasferimento di proprietà. std::auto_ptr sarebbe quindi più applicabili qui.

  

Internamente però, vorrei memorizzare il puntatore in una shared_ptr per evitare perdite di memoria in caso di eccezioni

Anche in questo caso, shared_ptr non può essere lo strumento migliore per quel lavoro. Per evitare perdite nel caso di eccezioni, scoped_ptr o auto_ptr sarebbero più adatti.

Utilizzare un shared_ptr ad un scoped_ptr alla risorsa (shared_ptr<scoped_ptr<Resource>>). In questo modo si ottiene il conteggio dei riferimenti di shared_ptr, che distruggerà automaticamente la risorsa se e solo se è ancora attaccato alla scoped_ptr. Ma si può staccare la scoped_ptr quando si è a portata di mano fuori della proprietà.

Come James è ben coperto non si può davvero staccare un puntatore condiviso.

Hai bisogno di più proprietari internamente, o stai trasferendo la proprietà dalla classe al cliente? In quel caso un std::auto_ptr potrebbe misura la fattura.

Se siete preoccupati per la semantica sorprendenti std::auto_ptr, si potrebbe tenere internamente da boost::scoped_ptr, e staccarlo in corrispondenza del punto di consegnare fuori - lasciando al cliente di eliminare manualmente o riporlo nel proprio puntatore intelligente.

Se si dispone di più proprietari dalla vostra parte si potrebbe usare un conteggio invadente. Internamente si potrebbe quindi utilizzare boost::intrusive__ptr, ma mano fuori il puntatore grezzo a livello di interfaccia. Il client può quindi lavorare manualmente con i conteggi ref, o conservarla in un boost::intrusive_ptr se stessi (ma non farli dipendono da esso)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top