2014-06-26 12 views
14

Io lavoro con un codebase che è stato parzialmente implementato da qualcuno che era innamorato di soluzioni troppo complesse per problemi semplici (ad esempio classi di template con due parametri che sono stati sempre istanziati per un paio di tipi). Una cosa che ha fatto è stata creare oggetti in un puntatore intelligente, e quindi fare in modo che l'oggetto memorizzi un puntatore debole su se stesso.Memorizza puntatore debole a self

class MyClass { 
    //... 
    boost::weak_ptr<MyClass> m_self; 
    //... 
}; 

boost::shared_ptr<MyClass> 
Factory::Factory::Factory::CreateMyClass() { 
    boost::shared_ptr<MyClass> obj(new MyClass(...)); 
    boost::weak_ptr<MyClass> p(obj); 
    obj->storeSelfPointer(p); 
    return obj; 
} 

La classe procede quindi utilizzare m_self bloccandolo e passando attorno al puntatore condivisa risultante.

Per la vita di me, non riesco a capire cosa stava cercando di realizzare. C'è qualche schema o idea che spiegherebbe questa implementazione? Mi sembra che questo sia completamente inutile e mi piacerebbe refactoring via.

EDIT: Devo dire che nessuna delle posizioni che utilizzano il puntatore intelligente risultante ottenuto dal blocco di m_self conserva effettivamente il puntatore intelligente.

+5

non conoscevano 'std :: shared_from_this' Credo –

+0

E 'C++ 98, roba più recente non viene utilizzato –

+3

Beh ok, è una versione di C++ 98 del' enable_shared_from_this' –

risposta

17

Un possibile utilizzo di questo "progetto" potrebbe essere l'utilizzo di m_self.lock() per generare da questo i puntatori condivisi.

Se si rimuove questo membro puntatore debole, il numero di riferimento trattenuto dal puntatore condiviso generato da this non sarebbe corretto.

Si ottiene lo stesso che std::enable_shared_from_this, abbastanza interessante, cppreference.com mentions this design:

Un'implementazione comune per enable_shared_from_this è di tenere un debole di riferimento (ad esempio std :: weak_ptr) a questo. I costruttori di std :: shared_ptr rilevano la presenza di una base enable_shared_from_this e assegnare appena creato std :: shared_ptr alla memorizzato internamente debole riferimento

e lo standard C++, sezione § 20.8.2.4 10, segnalata la stessa possibile implementazione:

I costruttori shared_ptr che creano puntatori uniche grado di rilevare la presenza di una base from_this enable_shared_- e assegnare lo shared_ptr appena creato sua __weak_this membe r


Possibile Refactoring:

  • Se si utilizza C++ 11, è possibile rimuovere il membro std::weak_ptr, ed eredita pubblicamente da std::enable_shared_from_this<T>. Dovresti recuperare un puntatore condiviso da questo chiamando shared_from_this().

  • Se non si utilizza C++ 11 ma è possibile utilizzare boost, utilizzare boost::enable_shared_from_this, vedere boost documentation. Dovresti recuperare un puntatore condiviso da questo chiamando shared_from_this().

  • Se non si utilizza C++ 11, e non è possibile utilizzare Boost, è possibile portare la proposta di attuazione della norma per la vostra base di codice, è abbastanza breve:

Codice : (copiata dal § 20.8.2.4 - 11, rimuovere sottolineature leader, e probabilmente vuole rinominarlo)

template<class T> class enable_shared_from_this { 
    private: 
    weak_ptr<T> __weak_this; 
    protected: 
    constexpr enable_shared_from_this() : __weak_this() { } 
    enable_shared_from_this(enable_shared_from_this const &) { } 
    enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; } 
    ~enable_shared_from_this() { } 
    public: 
    shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); } 
    shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); } 
}; 

e utilizzare shared_from_this() per fare un puntatore condiviso. Se copi questo codice, tieni presente che la costruzione di puntatori condivisi con altri mezzi non è non funziona. I costruttori di puntatori condivisi devono essere modificati (come spiegato dalla citazione standard sopra).

+1

Questa non è documentazione ufficiale –

+1

Vero. In realtà lo standard mostra la stessa identica implementazione possibile. – quantdev

+0

Sì, stavo cercando di confermarlo, ma la ricerca PDF non funzionava. Ora lo vedo. –