2013-10-02 16 views
8

Mi piacerebbe racchiudere un membro puntatore grezzo in un puntatore intelligente per impedire l'eliminazione all'interno di una classe di sviluppo. Il proprietario dell'oggetto sotto il puntatore è al di fuori della classe. Quindi, l'aspetto boost::shared_ptr e std::auto_ptr non si adatta. Di seguito è riportato un esempio ridotto:Creazione di weak_ptr <> dal puntatore raw

class Foo { 
    boost::weak_ptr<Bar> m_bar; 
public: 
    void setBar(const Bar *bar) { // bar created on heap 
    m_bar = bar;    // naturally compilation error 
    } 
}; 

Ovviamente, induce errore di compilazione. Qual è un modo corretto per inizializzare weak_ptr da un puntatore raw (se esistente)?

+0

possibile duplicato del [condiviso \ _ptr & debole \ _ptr conversioni] (http://stackoverflow.com/questions/17522020/shared-ptr-weak-ptr-conversions) –

+1

Se si desidera impedire la cancellazione di quel puntatore all'interno della classe, non chiamare 'delete' su di esso, e non fornire funzioni di accesso che espongono il puntatore ai client. 'weak_ptr' è pensato per la vista non proprietaria di un oggetto di proprietà di' shared_ptr'. Se tu fossi in grado di inserire quel puntatore in un 'weak_ptr', non avrebbe idea se il puntatore è scaduto, né mi impedisce di chiamare' delete m_bar.lock(). Get(); 'all'interno della classe. Non puoi mai rendere tutto al 100% a prova di idiota. – Praetorian

risposta

10

Non puoi farlo, puoi solo creare un weak_ptr da un shared_ptr o un altro weak_ptr. Quindi l'idea sarebbe che il proprietario del puntatore conservi un shared_ptr invece di un puntatore raw, e tutto dovrebbe essere ok.

1

Passa il puntatore condiviso invece del puntatore non elaborato e crea il puntatore debole da quel puntatore condiviso. Questo è davvero l'unico modo se il proprietario del puntatore è al di fuori di una classe.

4

Lo scopo di un puntatore debole è di non poter utilizzare il puntatore raw se è stato cancellato. Tuttavia, se si dispone di un puntatore raw, il puntatore debole non ha modo di sapere che è stato cancellato. Invece, devi avere shared_ptr da qualche parte che "possiede" il puntatore raw. Quindi puoi creare un weak_ptr che fa riferimento a shared_ptr.

Quando shared_ptr esce dall'ambito ed è l'ultimo puntatore intelligente "forte", elimina automaticamente il puntatore raw. Quindi, quando provate a bloccare il weak_ptr, vedrete che non è rimasto alcun puntatore "forte" e quindi l'oggetto non esiste.

2

Tutto quello che hai detto sembra perfettamente ragionevole, tranne una cosa:

void setBar(const Bar *bar) 

Questo non dovrebbe prendere un puntatore crudo. Dovrebbe prendere uno weak_ptr idealmente, o possibilmente uno shared_ptr se avete qualche argomento convincente.

Il proprietario effettivo dell'oggetto in questione deve costruire weak_ptr e quindi chiamare setBar con quello. Ciò preserva la semantica della proprietà. Sembra che quello che stai facendo è avere l'oggetto proprietario prendere un puntatore raw e passarlo a setBar. Ciò crea una lacuna semantica nella proprietà dell'oggetto.

5

L'unico modo per farlo è di entrare in possesso di un shared_ptr o weak_ptr che possiede il puntatore, altrimenti il ​​weak_ptr non ha modo di trovare il proprietario esistente al fine di condividere la proprietà con esso.

L'unico modo per ottenere un shared_ptr da un puntatore prima che è già proprietà di un altro shared_ptr è se Bar deriva da enable_shared_from_this<Bar>, allora si può fare

m_bar = bar->shared_from_this();