2009-03-10 12 views
9

Ho un progetto che mi piacerebbe utilizzare maggiormente i puntatori intelligenti. Nel complesso, ho avuto successo in questo obiettivo. Tuttavia, mi sono imbattuto in una cosa che non sono sicuro di quale sia la "migliore pratica".restituire un "puntatore" che deve essere tenuto da un puntatore intelligente

Fondamentalmente vorrei restituire un "puntatore" da una funzione, ma richiede che l'utente lo tenga in un puntatore intelligente. Non solo, non voglio mandare un particolare puntatore intelligente (condiviso o ambito).

Il problema è principalmente che non sembra esserci un modo corretto per aggiornare un scoped_ptr a un shared_ptr (sarebbe la soluzione ideale che penso). Capisco perché non hanno fatto questo, in quanto consentirebbe il trasferimento della proprietà che può portare ad alcuni problemi come quelli che hanno std::auto_ptr.

Tuttavia, il trasferimento di proprietà sembra una buona idea per questo caso. Quindi la mia idea è simile a questo:

// contrived example of factory pattern 
std::auto_ptr<A> func() { return std::auto_ptr<A>(new A); } 

questo funziona "ok" in quanto entrambi scoped_ptr e shared_ptr avere costruttori che prendono possesso di un std::auto_ptr.

Quindi la mia domanda è: questa è una buona pratica? C'è una soluzione migliore? L'unica vera alternativa sono stato in grado di elaborare con sta utilizzando un template come valore restituito in questo modo:

// similar to above example 
template <template <typename> class P> 
P<A> func() { return P<A>(new A); } 

che in realtà potrebbe funzionare bene, tranne che penso che sarebbe bisogno di qualche lavoro per farlo funziona anche con un scoped_ptr.

Pensieri?

risposta

11

Utilizzando std::auto_ptr è la buona pratica, infatti such example è stato suggerito da Bjarne Stroustrup.

La semantica di spostamento di auto_ptr fornisce gli strumenti giusti per gestirlo.

Ad esempio:

auto_ptr<Foo> make_foo() 
{ 
    return auto_ptr<Foo>(new Foo); 
} 

Foo *raw_pointer=make_foo().release(); 
shared_ptr<Foo> shared_pointer=make_foo(); 
auto_ptr<Foo> auto_pointer=make_foo(); 

Se si torna shared_ptr non si può fallback al normale puntatore, con auto_ptr è possibile. Puoi sempre aggiornare auto_ptr in condivisione ma non in altra direzione.

Un altro punto importante, shared_ptr utilizza il conteggio di riferimento atomico, che è molto più lento quello lavoro semplice e tuttavia completamente efficiente che fa auto_ptr.

P.S .: scoped_ptr è solo la versione di auto_ptr per i poeti --- non è copiabile e non ha il coordinaore predefinito . È più simile alla versione "meno confusa" di auto_ptr, rispetto a shared_ptr non è in tr1. Generalmente ci nessun molto vantaggi di usare scoped_ptr oltre auto_ptr

+0

shared_ptr nel build a thread singolo non utilizza il conteggio di riferimento atomico. –

+0

Hai ragione, ma per impostazione predefinita la spinta è generata nella versione multi-thread. – Artyom

+2

Il vantaggio dell'uso di scoped_ptr su auto_ptr è quando si desidera rendere chiaro che non si suppone di copiare il puntatore. Semplicemente non puoi con scoped_ptr. Si tratta di trasmettere le tue intenzioni, proprio come il tuo esempio con auto_ptr e il trasferimento di proprietà. –

3

Se si crea una fabbrica, è sufficiente restituire un puntatore. E l'utente della tua fabbrica può decidere da solo come e dove mettere questo puntatore.
Se è necessario imporre l'uso di un puntatore intelligente, è necessario limitare la scelta in quanto non si desidera che utilizzino quelli "errati".
So boost :: shared_ptr. Ma meglio dattiloscriverlo a MyClassPtr o MyClass :: ptr.
Ancora, le fabbriche sono come "nuove". Quando voglio inserisco il risultato del nuovo interno di std :: auto_ptr. Ma non voglio essere costretto a chiamare "release" tutte le volte che non voglio un puntatore intelligente.

+0

true, ma mi piacerebbe applicare l'uso di un puntatore intelligente, se possibile. –

+0

Sono d'accordo, siamo tutti adulti qui. Restituisce un puntatore nudo e consente all'utente del codice di decidere come catturare al meglio il valore restituito. Credo che il costruttore di shared_ptr da un auto_ptr stia andando via (auto_ptr sta per essere deprecato). –

+0

quando auto_ptr è privato in C++ 0x, unique_ptr lo sostituirà. Passerei a restituire unique_ptr allora. – Aaron

1

Con C++ 11 si dovrebbe essere in grado di utilizzare std::unique_ptr come gli altri tipi di puntatore intelligenti hanno costruttori che adottano un std::unique_ptr. Se mantieni un elenco interno di tali risorse, probabilmente vorresti usare std::shared_ptr.

Problemi correlati