Voici la documentation sur cppreference , ici le projet de travail.
Je dois admettre que je n'ai pas compris quel était le véritable objectif polymorphic_allocator
et quand / pourquoi / comment je devais l'utiliser.
A titre d'exemple, le pmr::vector
a la signature suivante:
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
Qu'est-ce que l' polymorphic_allocator
offre? Qu'est-ce que l' std::pmr::vector
offre aussi en ce qui concerne l'ancien std::vector
? Que puis-je faire maintenant que je n'ai pas pu faire jusqu'à présent?
Quel est le véritable objectif de cet allocateur et quand dois-je l'utiliser?
allocator<T>
intrinsèquement. Vous verrez donc de la valeur si vous utilisez fréquemment des allocateurs.Réponses:
Citation de choix de cppreference:
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 leAllocator
paramètre de modèle: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:
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 *
:Le principal problème restant, à mon avis, est qu'un
std::pmr::
conteneur n'est toujours pas compatible avec lestd::
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: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'utiliser
std::
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.
la source
std::pmr::
classes est-elle très probablement différente?reinterpret_cast
entre unstd::vector<X>
etstd::pmr::vector<X>
, si c'est ce que vous demandez.std::pmr::
conteneur n'est toujours pas compatible avec lestd::
conteneur équivalent utilisant l'allocateur par défaut" . Il n'y a pas non plus d'opérateur d'affectation défini de l'un à l'autre. En cas de doute, essayez-le: godbolt.org/z/Q5BKev (le code n'est pas exactement comme ci-dessus car gcc / clang a les classes d'allocation polymorphes dans un espace de noms "expérimental").template<class OtherA, std::enable_if< A can be constructed from OtherA > vector( vector<T, OtherA>&& )
constructeur. J'étais incertain et je ne savais pas où trouver un compilateur qui avait pmr compatible TS.polymorphic_allocator
est à un allocateur personnalisé commestd::function
à un appel direct de fonction.Il vous permet simplement d'utiliser un allocateur avec votre conteneur sans avoir à décider, au moment de la déclaration, lequel. Donc, si vous avez une situation où plus d'un allocateur serait approprié, vous pouvez utiliser
polymorphic_allocator
.Peut-être souhaitez-vous masquer quel allocateur est utilisé pour simplifier votre interface, ou peut-être souhaitez-vous pouvoir l'échanger contre différents cas d'exécution.
Vous avez d'abord besoin d'un code nécessitant un allocateur, puis vous devez vouloir pouvoir échanger celui qui est utilisé, avant de considérer le vecteur pmr.
la source
Un inconvénient des allocateurs polymorphes est qu'ils
polymorphic_allocator<T>::pointer
sont toujours justesT*
. Cela signifie que vous ne pouvez pas les utiliser avec des pointeurs sophistiqués . Si vous voulez faire quelque chose comme placer les éléments de avector
dans la mémoire partagée et y accéder viaboost::interprocess::offset_ptr
s , vous devez utiliser un ancien allocateur non polymorphe régulier pour cela.Ainsi, bien que les allocateurs polymorphes vous permettent de modifier le comportement d' allocation sans changer le type statique d'un conteneur, ils limitent ce qu'est une allocation .
la source