Domanda

Di solito uso un boost :: scoped_ptr per PIMPL (per un motivo perché non ricevo sorprese se dimentico di trattare con il costruttore di copie)

Con i modelli, tuttavia, non posso semplicemente inserire il distruttore nel file CPP in cui l'Impl è completamente definito al fine di soddisfare i requisiti del distruttore di Scoped_Ptr. Funziona comunque, ma non sono sicuro che sia GarantEed funzionare o semplicemente per caso. Esistono alcune "migliori pratiche" o standard? Scoped_ptr è il miglior puntatore intelligente per i pimpl in classi non copiabili?

template <class T> class C {
public:
    C(){}
    ~C(){}
private:
    boost::scoped_ptr<T> pimpl_;
};
È stato utile?

Soluzione

boost::shared_ptr Non richiede una definizione completa se non nel punto di istanza, nel costruttore, nel caso di un PIMPL. boost::shared_ptr è non appropriato per il idioma PIMPL, tuttavia, poiché fornisce semantica molto imprevisto (semantica di riferimento per l'assegnazione o la copia); Se vuoi davvero la complessità aggiunta di un puntatore intelligente, boost::scoped_ptr Sarebbe più appropriato (ma richiede una definizione completa nel punto che il suo distruttore è istanziato).

Per quanto riguarda i modelli, non ha senso utilizzare il linguaggio PIMPL per i dettagli di implementazione dall'intestazione. In assenza di export, tutti i dettagli di implementazione di un modello di classe devono essere inclusi ovunque il modello viene utilizzato, quindi la motivazione alla base del linguaggio PIMPL cessa di esistere.

Altri suggerimenti

Succede solo che Herb Sutter abbia iniziato a scrivere di nuovo i suoi GotW dopo molto tempo. Uno dei primi nuovi è correlato a "Firewall di compilation".

Potresti voler dare un'occhiata a:

GOTW #100: Firewall di compilation (Difficoltà: 6/10)

e

GOTW #101: Firewall compilation, parte 2 (Difficoltà: 8/10)

Due anni dopo capisco molto meglio la situazione, nell'interesse di mantenere le risposte di Overflow Stack pertinenti e aggiornate qui è come risponderei alla domanda oggi.

La premessa della mia domanda originale è in qualche modo imperfetta. Il motivo per utilizzare PIMPL-IDIOM è nascondere i dettagli dell'implementazione dal compilatore. Questo viene fatto memorizzando l'implementazione tramite un puntatore opaco (puntatore a un tipo di dati dichiarato ma non definito). Ciò può ridurre notevolmente la quantità di intestazioni necessarie da altre unità di compilation che interagiscono con la classe e quindi accelerano il tempo di compilazione. Nel caso del modello nella mia domanda è necessario che il tipo T sia completamente noto nel punto di istanza che in pratica richiede che il tipo di implici sia completamente definito ovunque C<ImplType> viene usato rendendo questo chiaramente non un esempio del pimpl-idiom nel classico senso del termine.

Ci sono altri motivi per contenere i dati delle classi tramite un puntatore privato, ad esempio consente una facile implementazione di mosse e swap senza lancio ed è anche buono se la tua classe deve soddisfare una forte garanzia di eccezione (vedi Copia e scambia Qual è il linguaggio di copia e swap?). D'altra parte, aggiunge un livello di indirezione (spesso risultante in una cache miss) su ogni accesso all'allocazione dell'impl e un heap/deallocazione alla creazione e alla distruzione dell'Impl. Queste possono essere penalità di prestazioni sostanziali, quindi questa soluzione non deve essere considerata un proiettile d'argento.

Se puoi usare C ++ 11, allora STD :: Unive

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