2010-07-31 14 views
6

Sto cercando di implementare un gestore di memoria personalizzato e mi chiedo se c'è un modo migliore per implementare questa funzione, come quando mi viene chiesto sull'aritmetica del puntatore vuoto, diverse persone pensavano che se avessi un vuoto * in C++, qualcosa era molto sbagliato.Custom Memory Manager

// allocates a page of memory. 
void ObjectAllocator::allocatePage() 
{  
    //if(OAStats_.PagesInUse_ >= Config_.MaxPages_) 
     //throw exception 

    void* buffer = ::operator new(OAStats_.PageSize_); // allocate memory, no constructor call. 

    // =============== Setup the PageList_ =============== 
    GenericObject* pNewNode = ::new(buffer) GenericObject(); // Construct GenericObject for the pagelist. 
    pNewNode->Next = PageList_->Next;       // pNewNode points to wherever PageList_ pointed to. 
    PageList_->Next = pNewNode;         // PageList_ points to pNewNode 
    pNewNode = NULL;           // dont need this handle anymore 
    buffer = static_cast<char*>(buffer) + sizeof(GenericObject); // move pointer to point after the generic object. 

    // =============== Setup the FreeList_ =============== 
    for(int i=0;i<Config_.ObjectsPerPage_;++i) 
    { 
     static GenericObject* pPreviousNode = NULL;   // static variable to hold the previous node 
     pNewNode = ::new(buffer) GenericObject();   // Construct GenericObject for the freelist. 
     pNewNode->Next = pPreviousNode; 
     pPreviousNode = pNewNode; 
     buffer = static_cast<char*>(buffer) + OAStats_.ObjectSize_; // move pointer by ObjectSize. 
     ++OAStats_.FreeObjects_; 
    } 
    FreeList_->Next = pNewNode; 

    ++OAStats_.PagesInUse_; 
    ++OAStats_.Allocations_; 
} 
+2

"molte persone pensavano che se avessi un vuoto * in C++, qualcosa era molto sbagliato." <- Non sarei d'accordo con questo. I puntatori del vuoto hanno i loro usi. Suppongo che dipenda dal fatto che tu faccia parte della comunità C++ "anti-C", oppure no. Tendo a dire che mentre sì, il C++ è un linguaggio di livello superiore rispetto a C, le persone spesso fanno cose di basso livello e quindi non c'è niente di sbagliato nell'usare le sue caratteristiche più "simili a C". – Stephen

+2

@Stephen: Perché tanti programmatori hanno questo riflesso istintivo che quando un concetto viene criticato, semplicemente * hanno * da dire "non è malvagio, ha i suoi usi". Suppongo che tu dica lo stesso di singleton e gotos. Ma in questo caso, quali sono gli usi di un vuoto *? Perché dovrebbe usare un vuoto * qui? – jalf

+1

@ Jalf Perché i commenti negativi rimangono nelle menti delle persone molto più che commenti positivi. Ciò significa che se qualcuno che è nuovo alla programmazione, o che non ha mai sentito parlare di X, legge un commento che indica X e dice che non dovresti mai usarlo, è probabile che prenda quella conoscenza e la consideri un fatto nella loro mente. Moreso, stavo semplicemente affermando un'opinione. Avresti risposto in modo simile se avessi eseguito il backup della vista "non utilizzare i puntatori void"? Qui no, non c'era motivo di usarlo, ma l'OP diceva semplicemente che la gente gli aveva detto di non usarli in generale quando codificava C++. – Stephen

risposta

7

Se è necessario un blocco di memoria per la memorizzazione di una stringa (ANSI a 8 bit), è opportuno dichiarare un puntatore a tale buffer come char e operare su di esso.

Nel tuo caso, hai bisogno di un blocco di memoria che sia un "blob", non ha un tipo intrinseco, quindi hai scelto correttamente void * per rappresentare quel blob.

Ora è necessario incrementare quel puntatore della dimensione di qualche oggetto. Non è possibile eseguire aritmetica su un puntatore vuoto per ovvi motivi, quindi cosa fai? Cast. Non c'è vergogna in questo.

5

In C++, su byte non elaborati, utilizzare un carattere * e non pensare meno a se stessi. È la cosa giusta da fare (tm). Soprattutto se lo avvolgi in un costrutto di livello superiore, come hai fatto tu.

+0

Perché il downvote, anonimo? Spiega e correggerò –

2

Non c'è nulla di intrinsecamente sbagliato nel vuoto *. Tuttavia, ciò che spesso vediamo sono persone che provengono da C che abusano del vuoto * quando dovrebbero fare qualcos'altro. Se gestisci i BLOB di memoria grezza, il vuoto * è perfettamente appropriato. Tuttavia, raramente c'è qualche altra ragione per farlo.

+0

+1. Per interessi, quali sono i modi tipici in cui "abusare del vuoto *"? – JBRWilkinson

+0

void * data, int size; memcpy (dati, buffer, dimensioni); invece di usare template e copy constructor. – Puppy