2012-01-30 14 views
8

Esiste una classe puntatore standard (o Boost) che è un puntatore non condiviso che funziona con tipi incompleti? Ho esaminato lo standard C++ 11 e la libreria boost e non riesco a trovarne uno, anche se sembra un tipo molto utile.Un puntatore intelligente non condiviso con tipi incompleti

Per esempio, mi piacerebbe essere in grado di fare tipi opachi usando un puntatore intelligente.

class A; 
    wrap_ptr<A> some_func(); 
    void other_func(A const &); 

A è un tipo opaco che può essere utilizzato per una varietà di funzioni. L'utente dell'interfaccia precedente ha solo una definizione incompleta di A, ma dovrebbe essere in grado di cancellare/ripristinare il puntatore. So che quanto sopra può essere fatto con un shared_ptr ma che ha un overhead che non voglio in questo particolare codice. unique_ptr ha la semantica della proprietà corretta, ma non può funzionare con un tipo incompleto. In teoria un wrapper dovrebbe avere solo l'overhead di avere un puntatore a un deleter.

Esiste un tipo in C++ 11 o nelle librerie di boost?

NOTA: Capisco che posso facilmente creare questo tipo, ma preferirei un tipo standard se possibile. Sembra che dovrebbe essere un tipo di puntatore intelligente fondamentale.


UPDATE: unique_ptr non sembra essere una buona opzione. Prima di tutto, l'overhead della sintassi si compenserebbe. In secondo luogo non sono convinto che possa essere tranquillamente utilizzato con un deleter personalizzato. Controllerò per vedere come potrebbe funzionare.

risposta

4

In realtà, unique_ptr può funzionare con tipi incompleti, purché si specifichi un deleter personalizzato.

Tuttavia, contrariamente a shared_ptr, questo influenza effettivamente il suo tipo, poiché il delet personalizzato viene precostato staticamente (come il secondo parametro del modello).

+0

Mentre tecnicamente vero, l'uso diretto di questo è sintatticamente ostile. Non si può semplicemente fare 'ptr_type (new T)' ma, assumendo si ottiene il typedef template corretto, si deve fare 'ptr_type (new T, T :: ~ T)'. –

+1

In realtà, guardando da vicino 'unique_ptr' non è possibile usare un deleter personalizzato con uno stato. La funzione 'reset' non consente di specificare un deleter, solo il costruttore lo fa, quindi l'aspetto dell'eliminazione personalizzata di' unique_ptr' è parzialmente rotto. –

+0

Non è necessario alcun deleter personalizzato, il tipo deve essere completato solo quando viene richiamato il distruttore di 'unique_ptr', il che significa che è possibile definire il distruttore dopo che la classe contenuta è stata completata. – Xeo

1

std::unique_ptr può gestire questo caso, ma non con il delet predefinito. È necessario scrivere un deleter in grado di gestire un tipo incompleto, quindi utilizzare std::unique_ptr<A,MyDeleter>.

9

essere chiari su unique_ptr: esso funziona con il tipo incompleto, ma se lo si utilizza in un colpo di testa di una classe del genere:

#include <memory> 

class A; 

class B 
{ 

std::unique_ptr<A> m_a; 

}; 

Non collegherà a seguito dell'attuazione deleter mancante. C'è una semplice soluzione a questo: basta definire il de-destructor della classe host in un cpp, anche se è vuoto o dovrebbe essere quello predefinito!

// B.hpp 
#include <memory> 

class A; 

class B 
{ 
public: 

    B(); 
    ~B(); 

private: 

std::unique_ptr<A> m_a; 

}; 

// B.cpp 

B::B(){} // or =default; (if you have a compiler providing it) 
B::~B(){} // or =default; (if you have a compiler providing it) 

Inoltre, leggere le risposte alla mia domanda c'è: Is std::unique_ptr<T> required to know the full definition of T?

E magari dare un'occhiata a come Pimpl (che implica tipo incompleto in un unique_ptr) si raccomanda di essere implmented da Herb Sutter: http://herbsutter.com/gotw/_100/

+1

Questo non è l'uso che voglio. Voglio usare il puntatore nel valore di ritorno della funzione, in un punto in cui il chiamante non vedrà mai il tipo completo. –

Problemi correlati