Domanda

Siamo praticamente passati all'utilizzo di boost :: shared_ptr in tutto il nostro codice, tuttavia abbiamo ancora alcuni casi isolati in cui utilizziamo std :: auto_ptr , comprese le classi singleton:

template < typename TYPE >
class SharedSingleton
{
public: 
    static TYPE& Instance()
    {
        if (_ptrInstance.get() == NULL)
            _ptrInstance.reset(new TYPE);
        return *_ptrInstance;
    }

protected: 
    SharedSingleton() {};

private:
    static std::auto_ptr < TYPE > _ptrInstance;
};

Mi è stato detto che c'è un'ottima ragione per cui questo non è stato creato un shared_ptr , ma per la mia vita non riesco a capire perché? So che auto_ptr alla fine verrà contrassegnato come ammortizzato nel prossimo standard, quindi vorrei sapere cosa / come posso sostituire questa implementazione .

Inoltre, ci sono altri motivi per cui potresti prendere in considerazione l'uso di un auto_ptr invece di un shared_ptr ? e vedi qualche problema trasferirsi in shared_ptr in futuro?


Modifica:

  1. Quindi, in risposta a " posso tranquillamente sostituire auto_ptr con shared_ptr nel codice sopra " ;, la risposta è sì - comunque prenderò un piccolo risultato .
  2. Quando auto_ptr viene infine contrassegnato come ammortizzato e passiamo a std :: shared_ptr , avremo bisogno di testare accuratamente il nostro codice per assicurarci di rispettare dalla diversa semantica della proprietà.
È stato utile?

Soluzione

auto_ptr e shared_ptr risolvono problemi completamente diversi. Uno non sostituisce l'altro.

auto_ptr è un sottile wrapper attorno ai puntatori per implementare RAII semantica , in modo che le risorse vengano sempre rilasciate, anche di fronte a eccezioni. auto_ptr non esegue alcun conteggio dei riferimenti o simili, non fa in modo che più puntatori puntino allo stesso oggetto durante la creazione di copie. In effetti, è molto diverso. auto_ptr è una delle poche classi in cui l'operatore di assegnazione modifica l'oggetto sorgente . Considera questa spina spudorata dalla pagina wikipedia auto_ptr :

int *i = new int;
auto_ptr<int> x(i);
auto_ptr<int> y;

y = x;

cout << x.get() << endl; // Print NULL
cout << y.get() << endl; // Print non-NULL address i

Nota come eseguire

y = x;

modifica non solo y ma anche x.

Il modello boost :: shared_ptr semplifica la gestione di più puntatori allo stesso oggetto e l'oggetto viene eliminato solo dopo che l'ultimo riferimento è uscito dall'ambito. Questa funzione non è utile nel tuo scenario, che (tenta di) implementare un Singleton . Nel tuo scenario, ci sono sempre 0 riferimenti a 1 riferimento all'unico oggetto della classe, se presente.

In sostanza, gli oggetti auto_ptr e gli oggetti shared_ptr hanno una semantica completamente diversa (ecco perché non puoi usare il primo in contenitori, ma farlo con il secondo va bene), e spero che abbiate buoni test per rilevare eventuali regressioni introdotte durante il porting del codice. : -}

Altri suggerimenti

Altri hanno risposto perché questo codice utilizza un auto_ptr anziché un shared_ptr . Per rispondere ad altre tue domande:

Cosa / come posso sostituire questa implementazione?

Usa boost :: scoped_ptr o unique_ptr (disponibile sia in Boost che nel nuovo standard C ++). Sia scoped_ptr che unique_ptr forniscono una proprietà rigorosa (e nessun sovraccarico di conteggio dei riferimenti) ed evitano la sorprendente semantica di eliminazione su copia di auto_ptr .

Inoltre, ci sono altri motivi per cui potresti prendere in considerazione l'uso di un auto_ptr invece di un shared_ptr ? E riscontri problemi nel passaggio a shared_ptr in futuro?

Personalmente, non userei un auto_ptr . Delete-on-copy è troppo intuitivo. Herb Sutter sembra essere d'accordo . Passare a scoped_ptr , unique_ptr o shared_ptr non dovrebbe offrire problemi. In particolare, shared_ptr dovrebbe essere una sostituzione drop-in se non ti interessa l'overhead del conteggio dei riferimenti. scoped_ptr è un sostituto drop-in se non si utilizzano le funzionalità di trasferimento della proprietà di auto_ptr . Se si utilizza il trasferimento di proprietà, unique_ptr è quasi una sostituzione drop-in, tranne per il fatto che è necessario chiamare esplicitamente move per trasferire la proprietà. Vedi qui per un esempio.

auto_ptr è l'unico tipo di puntatore intelligente che uso. Lo uso perché non uso Boost e perché in genere preferisco esplicitamente le mie classi orientate al business / alle applicazioni definire la semantica e l'ordine di cancellazione, piuttosto che dipendere da raccolte di, o singoli, puntatori intelligenti.

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