2010-05-25 17 views
7

boost::intrusive_ptr richiede intrusive_ptr_add_ref e intrusive_ptr_release da definire. Perché non è fornita una classe base che lo farà? C'è un esempio qui: http://lists.boost.org/Archives/boost/2004/06/66957.php, ma il poster dice "Non penso necessariamente che questa sia una buona idea". Perchè no?intrusive_ptr: Perché non è fornita una classe base comune?

Aggiornamento: Non penso che il fatto che questa classe possa essere usata impropriamente con l'ereditarietà multipla è una ragione sufficiente. Qualsiasi classe derivante da più classi base con il proprio conteggio di riferimento avrebbe lo stesso problema. Se questi conti vengono implementati tramite una classe base o no, non fa differenza.

Non penso che ci sia alcun problema con il multithreading; boost::shared_ptr offre il conteggio dei riferimenti atomici e anche questa classe.

+3

In una nota correlata, 'OSG :: ref_ptr' dalla libreria OpenSceneGraph utilizza un livello superiore classe base comune ('osg :: Referenced') per la sua implementazione del puntatore intelligente intrusivo. –

+3

E osg :: Referenced è compatibile con boost :: intrusive_ptr poiché fornisce le funzioni intrusive_ptr_add_ref() e intrusive_ptr_release(). Funziona perfettamente. –

risposta

2

Boost fornisce una struttura per questo. Può essere configurato sia per conteggio dei riferimenti thread-safe o filo-non sicuro:

#include <boost/intrusive_ptr.hpp> 
#include <boost/smart_ptr/intrusive_ref_counter.hpp> 

class CMyClass 
    : public boost::intrusive_ref_counter< 
           CMyClass, 
           boost::thread_unsafe_counter> 
    ... 

boost::intrusive_ptr<CMyClass> myPtr; 

http://www.boost.org/doc/libs/1_62_0/libs/smart_ptr/intrusive_ref_counter.html

+0

In altre parole, la risposta alla mia domanda è "ci dovrebbe essere, e ora c'è" :) – Jon

+0

Sembra che sia stato lì per un po ', ma si è mosso un po'. Ecco il primo riferimento al documento che ho trovato: http://www.boost.org/doc/libs/1_54_0/libs/log/doc/html/utilities.html#header.boost.log.utility.intrusive_ref_counter_hpp –

3

Il problema sarebbe con l'ereditarietà multipla. Se erediti da 2 oggetti che implementano questa base, hai 2 contatori per il tuo singolo oggetto ... e questo potrebbe causare il caos.

Così si avrebbe bisogno di fare le ptr_add e ptr_release metodi virtuali, in modo che la classe derivata può implementare un override per sincronizzare correttamente i contatori multipli in una sola volta ... Alcuni penalizzazione delle prestazioni qui, soprattutto perché la maggior parte delle volte che sarebbe essere completamente inutile (non ci sarebbe alcun override) perché è utile solo per l'ereditarietà multipla, dopo tutto.

E naturalmente in ambienti multi-threaded si potrebbero avere (per brevi periodi di tempo) contatori desincronizzati (il primo è stato incrementato ma il thread è stato interrotto prima che il secondo fosse) Non riesco a pensare a nessun problema causa, ma non è una situazione sensata.

Si aggiunge anche clutter alla classe, alcuni client potrebbero non aver bisogno del conteggio dei riferimenti dopo tutto (se creano l'oggetto nello stack).

penso che non sia una buona idea;)

+2

Eredità multipla: questo problema si verifica anche quando si hanno due classi base che implementano il proprio conteggio dei riferimenti. Se questo account viene implementato tramite una classe base o non fa alcuna differenza. Multi-Threaded: shared_ptr ha un incremento/decremento atomico, quindi anche questa classe. "alcuni client potrebbero non aver bisogno del conteggio dei riferimenti": questo è un motivo per cui non si dovrebbe usare intrusive_ptr, non perché non esiste una classe base. – Jon

+1

@Jon: concordo sull'ereditarietà multipla, infatti è possibile implementare il conteggio dei riferimenti intrusivi senza una classe base. Tuttavia non sono d'accordo sulle altre 2 osservazioni: per MT 'shared_ptr' fornisce semantica atomica facilmente perché ha solo un contatore, se hai diversi contatori da mantenere in uno stato coerente, allora hai bisogno di un blocco esplicito (non sono disponibili più op atomici) e questo significa overhead conseguente ... segui il coniglio bianco ... –

+1

Per la parte 'intrusive_ptr': Sono parziale qui, ma ho sempre pensato che l'approccio intrusivo fosse" sbagliato "nel senso che raggruppava insieme una classe" funzionale "e un comportamento" gestionale ". Quindi questa è effettivamente una critica al meccanismo di conteggio dei riferimenti intrusivi. Trovo più solido l'approccio 'shared_ptr' qui, e il fatto che tu non possa accidentalmente avere due contatori per un singolo set di' shared_ptr' è un bel bonus. –

4

E 'in modo da poter utilizzare intrusive_ptr con classi che già implementano aggiungere e rilascio.

+0

Ci sono altri motivi per usare intrusive_ptr (impronta di memoria, prestazioni, costruzione da un puntatore raw arbitrario) – Jon

+0

È la migliore ragione anche se IMHO –

Problemi correlati