154 votes

polymorphic_allocator : quand et pourquoi l'utiliser ?

Aquí est la documentation sur Référence cpp , aquí est le projet de travail.

Je dois admettre que je n'ai pas compris quel était le but réel de polymorphic_allocator et quand/pourquoi/comment je dois l'utiliser.
À titre d'exemple, le pmr::vector a la signature suivante :

namespace pmr {
    template <class T>
    using vector = std::vector<T, polymorphic_allocator<T>>;
}

Que fait le polymorphic_allocator offre ? Qu'est-ce que le std::pmr::vector aussi bien en ce qui concerne l'offre de l'ancienne std::vector ? Que puis-je faire maintenant que je n'étais pas capable de faire jusqu'à présent ?
Quel est le but réel de cet allocateur et quand dois-je l'utiliser en fait ?

1 votes

Ils essaient de surmonter certains problèmes allocator<T> a par nature. Vous y verrez donc de la valeur si vous utilisez fréquemment des allocateurs.

3 votes

Pertinent papier .

0 votes

Ce site papier explique en détail les idées derrière le polymorphic_allocator.

133voto

davmac Points 4317

Citation de choix de cppreference :

Ce polymorphisme d'exécution permet aux objets utilisant polymorphic_allocator de se comporter comme s'ils utilisaient des types d'allocateur différents au moment de l'exécution, malgré un type d'allocateur statique identique.

Le problème des allocateurs "ordinaires" est qu'ils modifient le type de conteneur. Si vous voulez un vector avec un allocateur spécifique, vous pouvez utiliser la fonction Allocator paramètre du 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 requiert un vecteur avec un allocateur par défaut, par exemple, ou assigner 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 par le biais de la répartition dynamique plutôt que par 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 nom d'utilisateur et un mot de passe. 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, tel que je le vois, est qu'une std::pmr:: n'est toujours pas compatible avec le conteneur équivalent std:: en utilisant l'allocateur par défaut. Vous devez prendre certaines décisions au moment où vous concevez une interface qui fonctionne avec un conteneur :

  • est-il probable que le conteneur transmis nécessite une allocation personnalisée ?
  • Dans ce cas, dois-je ajouter un paramètre de modèle (pour permettre des allocateurs arbitraires) ou dois-je imposer l'utilisation d'un allocateur polymorphe ?

Une solution modèle permet de cualquier y compris un allocateur polymorphe, mais présente d'autres inconvénients (taille du code généré, temps de compilation, code devant être exposé dans le fichier d'en-tête, potentiel de "contamination de type" supplémentaire qui repousse toujours le problème vers l'extérieur). D'autre part, la solution de l'allocateur polymorphe impose qu'un allocateur polymorphe debe être utilisé. Cela exclut l'utilisation de std:: qui utilisent l'allocateur par défaut, ce qui peut avoir des conséquences sur l'interfaçage avec le code existant.

Par rapport à un allocateur ordinaire, un allocateur polymorphe a quelques coûts mineurs, tels que l'overhead de stockage du pointeur memory_resource (qui est très probablement négligeable) et le coût de la répartition des fonctions virtuelles pour les allocations. Le principal problème, en fait, est probablement le manque de compatibilité avec le code existant qui n'utilise pas d'allocateurs polymorphes.

3 votes

Alors, est-ce que la disposition binaire pour std::pmr:: classes très susceptibles d'être différentes ?

14 votes

@EuriPinhollow vous ne pouvez pas reinterpret_cast entre un std::vector<X> y std::pmr::vector<X> si c'est ce que vous demandez.

0 votes

En gros : oui.

40voto

Yakk Points 31636

polymorphic_allocator est à un allocateur personnalisé comme std::function est un appel direct à une fonction.

Il vous permet simplement d'utiliser un allocateur avec votre conteneur sans avoir à décider, au moment de la déclaration, lequel. Ainsi, si vous êtes dans une situation où plus d'un allocateur serait approprié, vous pouvez utiliser la fonction polymorphic_allocator .

Peut-être voulez-vous cacher l'allocateur utilisé pour simplifier votre interface, ou peut-être voulez-vous pouvoir le remplacer pour différents cas d'exécution.

Tout d'abord, vous devez avoir un code qui a besoin d'un allocateur, puis vous devez vouloir être capable de permuter celui qui est utilisé, avant de considérer le vecteur pmr.

10voto

Maxpm Points 5293

L'un des inconvénients des allocateurs polymorphes est que polymorphic_allocator<T>::pointer est toujours juste T* . Cela signifie que vous ne pouvez pas les utiliser avec pointeurs fantaisistes . Si vous voulez faire quelque chose comme placer les éléments d'un fichier vector dans la mémoire partagée et y accéder par le biais de boost::interprocess::offset_ptr s vous devez utiliser un bon vieil allocateur non polymorphe pour cela.

Ainsi, bien que les allocateurs polymorphes vous permettent de varier l'allocation comportement sans changer le type statique d'un conteneur, ils limitent ce qu'une allocation est.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X