2009-10-21 14 views
8

Vorrei utilizzare diverse istanze di una classe di allocatore personalizzato STL per gestire diversi spazi di memoria e quindi essere in grado di specificare un'istanza allocator in un contenitore STL in modo tale che ogni contenitore estragga solo da il suo spazio di memoria assegnato. Ma non vedo come posso farlo. Vedo come posso passare un tipo di allocatore nei parametri del template di un container STL, ma voglio qualcosa di simile a passare un'istanza di allocator nel costruttore di un container STL. C'è un modo per farlo in STL?Allocatori personalizzati STL per gestire diversi spazi di memoria

risposta

17

Sfortunatamente gli allocatori STL non possono avere lo stato (o almeno devono stare molto attenti a come viene usato quello stato) - ogni istanza di un particolare tipo di allocatore deve essere equivalente per i container STL che funzionano efficacemente con essi. Non ricordo i dettagli in questo momento, ma so che Scott Meyers discute a lungo questo problema in "Effective STL", Elemento 10: Presta attenzione alle convenzioni e alle restrizioni degli allocatori.

Tuttavia, è possibile avere su modelli ripartitori che sono molto simili, con le differenze tra i ripartitori di essere incapsulato nel tipo allocatore e utilizzare diversi 'istanze' del modello allocatore (ogni template 'esemplificazione' è un tipo diverso) . Ancora una volta, il mio ricordo è che Meyers ne discute abbastanza chiaramente.

Per esempio vedere questo paragrafo da un articolo di Anthony Aue, "Improving Performance with Custom Pool Allocators for STL":

Un avvertimento potenzialmente più grave è che, dal momento che l'allocatore utilizza i dati non statici, non è tecnicamente standard compliant, perché richiede l'standard che ripartitori dello stesso tipo essere equivalente. Vedere STL effettivo (elemento 10) per una spiegazione esaustiva del problema. Ciò equivale a richiedere che un allocatore per un determinato tipo sia in grado di deallocare la memoria allocata da qualsiasi altra istanza di un allocatore per quel tipo. Per molti usi di contenitori standard, questo requisito non è necessario (alcuni potrebbero dire Draconian). Tuttavia, ci sono due casi in cui questo requisito è assolutamente necessario: list :: splice and swap(). Il caso di swap() è particolarmente serio perché è necessario per implementare determinate operazioni sui contenitori in modo eccezionalmente sicuro (vedere Eccezionale C++, elemento 12). Tecnicamente, lo swap potrebbe essere (e in alcuni casi, è) implementato di fronte agli allocatori che non sono paragonabili allo stesso modo: gli elementi potrebbero essere copiati o gli allocatori potrebbero essere scambiati insieme ai dati, ma non è sempre così. Per questo motivo, se stai usando swap() o list :: splice, dovresti assicurarti di usare HoldingPolicySingleton; altrimenti, sei destinato a imbatterti in un comportamento davvero sgradevole.

Vedere anche la discussione di Stephan T. Lavavej in this newsgroup thread.

Mi aggiornerò più tardi stasera se qualcun altro non fornisce i dettagli nel frattempo.

+2

Vale la pena notare, tuttavia, che C++ 0x richiederà il supporto per allocatori non uguali. –

+1

Hai ragione che vale la pena notare - FAQ di Stroustup su C++ 0x "Scoped Allocators": http://www.research.att.com/~bs/C++0xFAQ.html#scoped-allocator –

+0

+1 - Vorrei poter sbattere questa risposta di più. Gli allocatori in STL sono stati piuttosto ostili - attraggono più bug esoterici che funzionalità. – Fox

0

Forse potresti codificare un set di tipi di allocatore che contiene un puntamento statico per separare gli spazi di memoria.

Quindi, quando il contenitore STL costruisce l'allocatore, l'allocatore utilizza la memoria assegnata a tale allocatore.

Per semplicità, si supponga di voler utilizzare due spazi di memoria. Crea due tipi di allocatore, uno per ogni spazio. Passare il tipo di allocatore ai costruttori del contenitore STL come richiesto.

6

I contenitori STL consentono di inoltrare l'allocatore come argomento al costruttore.

Per esempio qui sono i costruttori appropriate per il vettore:

explicit vector(const Allocator& = Allocator()); 
explicit vector(size_type n, const T& value = T(), 
    const Allocator& = Allocator()); 
template <class InputIterator> 
vector(InputIterator first, InputIterator last, 
    const Allocator& = Allocator()); 

Per impostazione predefinita, basta usare un allocatore di default costruito.

Problemi correlati