Citation de choix de cppreference:
Ce polymorphisme à l'exécution permet aux objets utilisant polymorphic_allocator de se comporter comme s'ils utilisaient différents types d'allocateur au moment de l'exécution malgré le même type d'allocateur statique
Le problème avec les allocateurs «normaux» est qu'ils changent le type de conteneur. Si vous voulez un vector
avec un allocateur spécifique, vous pouvez utiliser le Allocator
paramètre de modèle:
auto my_vector = std::vector<int,my_allocator>();
Le problème maintenant est que ce vecteur n'est pas du même type qu'un vecteur avec un allocateur différent. Vous ne pouvez pas le passer à une fonction qui nécessite un vecteur d'allocateur par défaut, par exemple, ou affecter deux vecteurs avec un type d'allocateur différent à la même variable / pointeur, par exemple:
auto my_vector = std::vector<int,my_allocator>();
auto my_vector2 = std::vector<int,other_allocator>();
auto vec = my_vector; // ok
vec = my_vector2; // error
Un allocateur polymorphe est un type d'allocateur unique avec un membre qui peut définir le comportement de l'allocateur via une répartition dynamique plutôt que via le mécanisme de modèle. Cela vous permet d'avoir des conteneurs qui utilisent une allocation spécifique et personnalisée, mais qui sont toujours d'un type commun.
La personnalisation du comportement de l'allocateur se fait en donnant à l'allocateur un std::memory_resource *
:
// define allocation behaviour via a custom "memory_resource"
class my_memory_resource : public std::pmr::memory_resource { ... };
my_memory_resource mem_res;
auto my_vector = std::pmr::vector<int>(0, &mem_res);
// define a second memory resource
class other_memory_resource : public std::pmr::memory_resource { ... };
other_memory_resource mem_res_other;
auto my_other_vector = std::pmr::vector<int>(0, &mes_res_other);
auto vec = my_vector; // type is std::pmr::vector<int>
vec = my_other_vector; // this is ok -
// my_vector and my_other_vector have same type
Le principal problème restant, à mon avis, est qu'un std::pmr::
conteneur n'est toujours pas compatible avec le std::
conteneur équivalent utilisant l'allocateur par défaut. Vous devez prendre certaines décisions au moment de concevoir une interface qui fonctionne avec un conteneur:
- est-il probable que le conteneur transmis nécessite une allocation personnalisée?
- si c'est le cas, dois-je ajouter un paramètre de modèle (pour permettre des allocateurs arbitraires) ou dois-je exiger l'utilisation d'un allocateur polymorphe?
Une solution de modèle autorise n'importe quel allocateur, y compris un allocateur polymorphe, mais présente d'autres inconvénients (taille du code généré, temps de compilation, le code doit être exposé dans le fichier d'en-tête, potentiel de "contamination de type" supplémentaire qui continue de pousser le problème vers l'extérieur). Une solution d'allocateur polymorphe, d'autre part, dicte qu'un allocateur polymorphe doit être utilisé. Cela empêche d'utiliserstd::
conteneurs qui utilisent l'allocateur par défaut et peut avoir des implications pour l'interfaçage avec le code hérité.
Comparé à un allocateur ordinaire, un allocateur polymorphe a des coûts mineurs, tels que la surcharge de stockage du pointeur memory_resource (qui est probablement négligeable) et le coût de l'envoi de fonction virtuelle pour les allocations. Le problème principal, en réalité, est probablement le manque de compatibilité avec le code hérité qui n'utilise pas d'allocateurs polymorphes.
allocator<T>
intrinsèquement. Vous verrez donc de la valeur si vous utilisez fréquemment des allocateurs.