2010-03-24 3 views
19

J'essaie d'écrire une classe de conteneur qui utilise des allocateurs STL. Ce que je fais actuellement est d'avoir un députéComment utiliser std :: allocator dans ma propre classe de conteneur

std::allocator<T> alloc_; 

(ce sera plus tard templated afin que l'utilisateur peut choisir un allocateur différent), puis appelez

T* ptr = alloc_.allocate(1,0); 

pour obtenir un pointeur vers un nouveau objet 'T' alloué (et utilisé alloc_.construct pour appeler le constructeur, voir la réponse ci-dessous). Cela fonctionne avec la bibliothèque GNU C++. Cependant, avec STLPort sur Solaris, cela ne réussit pas à faire le bon choix et conduit à toutes sortes d'erreurs de corruption de mémoire bizarres. Si je fais à la place

std::allocator_interface<std::allocator<T> > alloc_; 

puis tout fonctionne comme il se doit.

Quelle est la bonne façon d'utiliser stl :: allocator? La version STLPort/Solaris ne peut pas être compilée avec g ++, mais g ++ est-il correct?

+7

Il n'y a rien appelé 'allocator_interface' dans la bibliothèque standard. – AraK

Répondre

8

Quelque chose que vous pourriez faire est d'avoir votre propre allocator personnalisé que vous pouvez utiliser pour voir comment les conteneurs standard interagissent avec les allocateurs. Stephan T. Lavavej a posté un joli, simple appelé le mallocator. Laisse tomber dans un programme de test qui utilise différents conteneurs STL et vous pouvez facilement voir comment l'allocateur est utilisé par les conteneurs standard:

pas toutes les fonctions d'interface dans le mallocator (par exemple comme construct() et destroy()) sont instrumentés avec la sortie de trace, donc vous pourriez vouloir laisser tomber les instructions de trace pour voir plus facilement comment les conteneurs standards pourraient utiliser ces fonctions sans avoir recours à un débogueur.

Cela devrait vous donner une bonne idée de la façon dont vos conteneurs devraient utiliser un allocator personnalisé.

+0

Malheureusement, il ne trace pas 'construct', ce qui est la fonction qu'il n'utilisait pas: -/ –

+0

C'est vrai (j'ai mentionné cette lacune dans ma réponse), et j'entendais que ma réponse soit plus ou moins une barre latérale à votre réponse qui souligne le problème directement. Lavavej a publié le 'mallocator' comme un simple exemple d'un allocateur personnalisé. Je proposais que cela puisse aussi être utilisé comme un moyen facile d'obtenir un aperçu de la façon dont les conteneurs utilisent les allocateurs, mais qu'il pourrait être nécessaire de faire quelques modifications mineures pour améliorer le traçage à cette fin. –

16

Vous devez à la fois allouer et construire avec l'allocateur. Quelque chose comme ceci:

T* ptr = alloc_.allocate(1,0); 
alloc_.construct(ptr, value); 

Beaucoup de choses sont carrément cassé si vous ne commencez pas avec un objet correctement construit. Imaginez qu'un std::string soit alloué mais non construit. Lorsque vous essayez de l'assigner, il va d'abord essayer de nettoyer son ancien contenu en libérant des données, qui seront bien sûr des valeurs parasites du tas et du plantage.

+0

Oui, je sais, je l'ai fait, même si j'ai utilisé le placement new au lieu de std :: allocator :: construct (ce qui n'est probablement pas recommandé, donc j'ai changé cela maintenant). Cependant, il s'avère que STLPort 4.x ne connaît pas std :: allocator :: construct soit ... –

+0

Si STLPort n'a pas 'std :: allocator :: construct' alors il est cassé, ne vous embêtez même pas en l'utilisant. Je peux vous dire avec certitude que 5.1.5 (la version que j'ai installée l'a et fonctionne bien). –

+1

J'ai cherché à satisfaire ma curiosité, STLPort 4.x ** a ** un standard conforme à la norme 'std :: allocator'. Dans 4.6, la fonction 'construct' se trouve sur la ligne 365 de' stlport/stl/_alloc.h'.Si cela ne fonctionne pas, votre installation n'est pas correcte. –

Questions connexes