2010-04-17 13 views
8

Attualmente alloco la memoria per gli array utilizzando il mm_malloc specifico per MS. Allineo la memoria, dato che sto facendo dei calcoli pesanti e la vettorizzazione sfrutta l'allineamento. Mi stavo chiedendo se qualcuno sa come sovraccaricare il nuovo operatore per fare la stessa cosa, dato che mi sento sporco malloc'ing ovunque (e alla fine mi piacerebbe anche compilare su Linux)? Grazie per qualsiasi aiutorestituisce memoria allineata con nuova?

risposta

10

Prima di tutto, è importante notare che new e possono essere sovraccaricati globalmente o solo per una singola classe. Entrambi i casi sono mostrati in this article. Inoltre, è importante notare che se sovraccarichi lo new quasi certamente vuoi sovraccaricare anche lo delete.

Ci sono alcune note importanti circa operator new e operator delete:

  1. Lo standard C++ richiede che un puntatore valido viene restituito anche se la dimensione passata è 0.
  2. C'è anche operator new[] e operator delete[], quindi non dimenticare di sovraccaricare quelli.
  3. Le classi derivate ereditano operator new e i suoi fratelli, quindi assicurati di sovrascriverli.

In Effective C++, punto 8, Scott Meyers include alcuni esempi pseudocodish:

void * operator new(size_t size)  // your operator new might 
{          // take additional params 
    if (size == 0) {      // handle 0-byte requests 
    size = 1;       // by treating them as 
    }          // 1-byte requests 
    while (1) { 
    attempt to allocate size bytes; 
    if (the allocation was successful) 
     return (a pointer to the memory); 

    // allocation was unsuccessful; find out what the 
    // current error-handling function is (see Item 7) 
    new_handler globalHandler = set_new_handler(0); 
    set_new_handler(globalHandler); 

    if (globalHandler) (*globalHandler)(); 
    else throw std::bad_alloc(); 
    } 
} 


void operator delete(void *rawMemory) 
{ 
    if (rawMemory == 0) return; // do nothing if the null 
           // pointer is being deleted 
    deallocate the memory pointed to by rawMemory; 
    return; 
} 

Per ulteriori informazioni, mi piacerebbe sicuramente raccolgo Effective C++.

+0

quindi, dovrei semplicemente inserirlo in un'intestazione e fare riferimento a quell'intestazione in tutti i miei file? – Steve

+0

Bene, avresti messo le definizioni in un file sorgente, ma sì. – rlbond

+0

solo una piccola nota a piè di pagina: puoi anche definire un operatore 'new (size_t count, size_t alignment)' in modo che tu possa passare esplicitamente l'allineamento come argomento all'operatore new. Questo sarebbe chiamato come 'nuovo (allineamento) AlignedType' – user666412

2

new è necessario per restituire un pointer [...] suitably aligned so that it can be converted to a pointer of any complete object type (§3.7.3.1 dello standard).

FWIW, C++ 0x aggiungerà un alignof che vi dirà l'allineamento necessaria per un determinato tipo.

+3

Sfortunatamente, per qualche motivo non l'ho mai capito, i compilatori generalmente non applicano questa regola per i tipi di SIMD a 128 bit. In genere sono ancora 'new''ed con allineamento a 8 byte, credo. – jalf

+0

@jalf: due motivi: (1) le allocazioni più allineate sono, maggiore è l'overhead di allocazione per blocco. Se si effettuano molte allocazioni a 17 byte, si vedrebbe una differenza tra 16 allineamenti e solo 4 allineamenti. (2) (specifico per GNU), glibc fa meno ipotesi specifiche della piattaforma rispetto a GCC, e in realtà non sa né si cura di quale sia il tipo più grande che qualche compilatore su un sistema potrebbe supportare. Ma GCC "vuole" passare malloc direttamente a glibc, non aggiungere il proprio meccanismo di allineamento, con un sovraccarico ancora maggiore di quello di malloc. Ho letto un'interessante discussione pubblica a riguardo. –

+0

...infine, il compilatore potrebbe in teoria scegliere di allineare semplicemente le chiamate a 'new SIMD_Type', evitando il sovraccarico su tutte le allocazioni oltre 15 byte. Ma sarebbe ancora sbagliato, perché se lo farai allora dovresti anche allineare le chiamate a 'new char [sizeof (SIMD_Type)]'. Il consenso è far finta che i tipi di SIMD non siano "veri e propri tipi built-in", sono cose speciali che devono essere allocate appositamente. –

Problemi correlati