2012-07-26 17 views
5

Attualmente mi sto occupando di C++ per la codifica di livello inferiore con opengl. Vengo da uno sfondo pesante objc quindi ho un po 'di comprensione sulla gestione della memoria, ma non riesco a capire come la libreria "boost" gestisce i tipi di container come ptr_vector.In che modo ptr_vector gestisce la memoria?

Penso che il mio problema sia legato al fatto che non ho idea di come ptr_vector gestisca la distruzione di se stesso e dei suoi oggetti.

prega di dare un'occhiata al seguente codice:

// Header file 
... 
ptr_vector<IObject3D> objects; 
... 

// Implementation file 
... 
void ApplicationEngine::init() 
{ 
    WavefrontObject3D *object = new WavefrontObject3D("Ninja.obj"); 
    objects.push_back(object); 
} 
... 

Così, per la realtà in discussione: sto creando una perdita di qui, attraverso la variabile "oggetto"?

Sono abituato a trattenere e rilasciare i miei oggetti manualmente con le chiamate esplicite a objc: in precedenza ho dovuto alloc init il WavefrontObject3D object, inserirlo in un array e poi release che lo stesso oggetto per evitare perdite.

Tuttavia, quando aggiungo uno delete object dopo il push_back, viene chiamato il decostruttore di WavefrontObject3D object. Questo mi dà un suggerimento che il ptr_vector non mantiene la variabile object. La mia ipotesi è corretta?

aggiuntive, ma correlata, domanda: diciamo che voglio distruggere la classe contenente ApplicationEngine non devo chiamare un qualche tipo di decostruttore sul ptr_vector o gli elementi che gestisce?

+0

'Ma quando aggiungo un oggetto delete dopo la chiamata push_back viene chiamato il decostruttore dell'oggetto WavefrontObject3D. Questo è il motivo per cui' delete' è fatto. Chiama il distruttore sull'istanza a cui punta il puntatore. – Nobody

+1

Penso che dovresti leggere [RAII] (http://stackoverflow.com/q/395123/20984), che è il modo in cui viene gestita la maggior parte della gestione della memoria nel cosiddetto C++ "moderno". –

+0

Grande risorsa @LucTouraille! Esattamente il modo in cui volevo avvicinarmi al C++. – polyclick

risposta

5

No, questo non crea una perdita. Tutti i contenitori ptr_* eliminano gli oggetti che sono memorizzati in essi quando il contenitore esce dall'ambito.

Se si elimina l'oggetto dopo averlo aggiunto al contenitore, verrà creato undefined behavior poiché il contenitore tenterà di eliminarlo nuovamente.

Domanda aggiuntiva: No, se si memorizza il valore ptr_vector in base al valore, la durata viene gestita dall'ambito della classe circostante.

Scriviamo una semplice implementazione di ptr_vector. Non ha supporto per iteratori indiretti e delet personalizzati e molte altre cose, ma mostra i principi usati.

template <typename T> 
class ptr_vector { 
public: 
    // assume control over it 
    void push_back(T* x) 
    { if(x) c_.push_back(x); else throw bad_pointer(); } 

    ~ptr_vector() { 
    // delete everything that is stored here 
    for(auto x : c_) delete x; 
    } 
private: 
    std::vector<T*> c_; 
}; 


// a user class 
struct user_class { 
    void addSomething() { x.push_back(new int(23)); } 
    ptr_vector<int> x; 
}; 

Se la classe utente va fuori portata, il distruttore di ptr_vector sarà essere chiamati e tutta la memoria sarà recuperato. Nessuna perdita in vista.

+0

+1 per mostrare il funzionamento interno di 'ptr_vector';) – polyclick

0

ptr_vector libererà tutti gli elementi nel suo distruttore, quindi non devi fare nulla di più di quello che fai già, cioè creare gli oggetti, aggiungerli allo ptr_vector e lasciare la gestione ad esso. Chiamando lo delete in modo esplicito, l'oggetto verrà distrutto due volte (una volta quando lo si richiede e di nuovo quando termina lo ptr_vector). In altre parole, ptr_vector non duplica l'oggetto.

Quando il ApplicationEngine termina, se ha un'istanza di ptr_vector, verrà chiamato il distruttore di quel vettore, che a sua volta cancella gli oggetti aggiunti.

2
void push_back(T* x); 

Requisiti: x = 0 Effetti: inserisce il puntatore nel contenitore e assume la proprietà di getta: bad_pointer se x == 0 sicurezza Eccezione: forte garanzia

template 
    < 
     class T, 
     class CloneAllocator = heap_clone_allocator, 
     class Allocator  = std::allocator<void*> 
    > 
    class ptr_vector : public ptr_sequence_adapter 
           < 
            T, 
            std::vector<void*,Allocator>, 
            CloneAllocator 
           > 

Quindi è possibile specificare il proprio CloneAllocator e non eliminare elementi memorizzati in ptr_vector, ma heap_clone_allocator (il par predefinito per CloneAllocator) elimina tutti gli elementi memorizzati nel distruttore.

http://www.boost.org/doc/libs/1_50_0/libs/ptr_container/doc/reference.html#class-heap-clone-allocator

Problemi correlati