2010-12-13 15 views
10

Sto solo giocando in giro con i puntatori intelligenti nel prossimo nuovo standard C++. Tuttavia non riesco a cogliere l'uso della funzione shared_from_this. Ecco quello che ho:enable_shared_from_this (C++ 0x): quello che sto facendo di sbagliato?

#include <iostream> 
#include <memory> 

class CVerboseBornAndDie2 : public std::enable_shared_from_this<CVerboseBornAndDie2> 
{ 
public: 
    std::string m_Name; 
    CVerboseBornAndDie2(std::string name) : m_Name(name) 
    { 
     std::cout << m_Name << " (" << this << ") is born!" << std::endl; 
    } 
    virtual ~CVerboseBornAndDie2() 
    { 
     std::cout << m_Name << " (" << this << ") is dying!" << std::endl; 
    } 
}; 

int main(){ 
    CVerboseBornAndDie2* vbad = new CVerboseBornAndDie2("foo"); 
    std::shared_ptr<CVerboseBornAndDie2> p = vbad->shared_from_this(); 
} 

e genera un'eccezione std :: bad_weak_ptr nella linea

std::shared_ptr<CVerboseBornAndDie2> p = vbad->shared_from_this(); 

se io invece faccio

std::shared_ptr<CVerboseBornAndDie2> p(vbad); 

funziona e posso poi fare

std::shared_ptr<CVerboseBornAndDie2> p2 = p.get()->shared_from_this(); 

così deve l'oggetto appartenere a uno shared_ptr prima che io possa usare shared_from_this? Ma come posso sapere questo in anticipo?

risposta

22

È una condizione preliminare di utilizzare shared_from_this che deve esistere almeno uno shared_ptr proprietario dell'oggetto in questione. Ciò significa che è possibile utilizzare solo shared_from_this per recuperare un shared_ptr che possiede un oggetto a cui si dispone di un riferimento o puntatore, non è possibile utilizzarlo per scoprire se un tale oggetto è di proprietà di un shared_ptr.

È necessario rielaborare il progetto in modo che sia garantito che qualsiasi oggetto di questo tipo sia gestito da un shared_ptr o che non si abbia mai bisogno di conoscerlo o infine (e meno desiderabilmente) di creare un altro modo di gestire questa conoscenza

+0

Non potresti semplicemente mettere un blocco di prova attorno a una chiamata a shared_from_questo se volevi sapere se l'oggetto è tenuto da un shared_ptr? Non so come sia specificato nello standard (imminente), ma non sembra essere un comportamento indefinito - sta generando un'eccezione. – nobar

+1

@nobar: questo sarebbe inferiormente pericoloso. Si farebbe affidamento su dettagli di implementazione non documentati. 'shared_from_this' non è un metodo per verificare se un oggetto è di proprietà di un puntatore condiviso; è un metodo per recuperare un puntatore condiviso da un oggetto che _know_ è di proprietà di un puntatore condiviso. –

+0

Penso che tu abbia ragione. La bozza C++ 0x dice "Ci deve essere almeno un'istanza shared_ptr p che possiede & t.", Ma non dice cosa succede altrimenti. Essa mostra un'implementazione in termini di weak_ptr (che implicherebbe che un'eccezione verrà generata in caso di errore), ma che è solo un "suggerimento". Mi chiedo se la gestione degli errori sarà eventualmente meglio specificata. – nobar

15

Per estendere Charles risposta, quando si utilizza enable_shared_from_this di solito si desidera qualcosa di simile qui di seguito in modo da garantire che esiste uno shared_ptr.

class my_class : public std::enable_shared_from_this<my_class> 
{ 
public: 
    static std::shared_ptr<my_class> create() // can only be created as shared_ptr 
    { 
     return std::shared_ptr<my_class>(new my_class()); 
    } 
private 
    my_class(){} // don't allow non shared_ptr instances. 
}; 
+1

'create()' dovrebbe essere 'statico', no? –

+0

@ abyss.7: infatti. – ronag

+1

E per avere la condivisione di default, si potrebbe usare qualcosa sulla falsariga di: 'try {return shared_from_this(); } catch (const bad_weak_ptr &) {return make_shared (); } ' –

Problemi correlati