Auswahl Zitat aus cppreference:
Dieser Laufzeitpolymorphismus ermöglicht es Objekten, die polymorphic_allocator verwenden, sich so zu verhalten, als ob sie zur Laufzeit trotz des identischen statischen Allokatortyps unterschiedliche Allokatortypen verwenden würden
Das Problem bei "regulären" Allokatoren ist, dass sie den Typ des Containers ändern. Wenn Sie einen vector
mit einem bestimmten Allokator möchten , können Sie den Allocator
Vorlagenparameter verwenden:
auto my_vector = std::vector<int,my_allocator>();
Das Problem ist nun, dass dieser Vektor nicht vom gleichen Typ ist wie ein Vektor mit einem anderen Allokator. Sie können es nicht an eine Funktion übergeben, für die beispielsweise ein Standardzuweisungsvektor erforderlich ist, oder zwei Variablen mit einem anderen Zuordnungstyp derselben Variablen / demselben Zeiger zuweisen, z.
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
Ein polymorpher Allokator ist ein einzelner Allokatortyp mit einem Element, das das Allokatorverhalten über den dynamischen Versand und nicht über den Vorlagenmechanismus definieren kann. Auf diese Weise können Sie Container haben, die eine bestimmte, benutzerdefinierte Zuordnung verwenden, aber immer noch einen gemeinsamen Typ haben.
Die Anpassung des Allokatorverhaltens erfolgt, indem dem Allokator Folgendes zugewiesen wird 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
Das verbleibende Hauptproblem ist meines Erachtens, dass ein Container mit dem Standard-Allokator std::pmr::
immer noch nicht mit dem entsprechenden std::
Container kompatibel ist . Sie müssen einige Entscheidungen treffen, wenn Sie eine Schnittstelle entwerfen, die mit einem Container funktioniert:
- Ist es wahrscheinlich, dass der übergebene Container eine benutzerdefinierte Zuordnung erfordert?
- Wenn ja, sollte ich einen Vorlagenparameter hinzufügen (um beliebige Allokatoren zuzulassen) oder die Verwendung eines polymorphen Allokators vorschreiben?
Eine Vorlagenlösung ermöglicht jeden Allokator, einschließlich eines polymorphen Allokators, hat jedoch andere Nachteile (generierte Codegröße, Kompilierungszeit, Code muss in der Header-Datei verfügbar gemacht werden, Potenzial für weitere "Typkontamination", die das Problem immer weiter nach außen drückt). Eine polymorphe Allokatorlösung schreibt andererseits vor, dass ein polymorpher Allokator verwendet werden muss . Dies schließt die Verwendung von std::
Containern aus, die den Standardzuweiser verwenden, und kann Auswirkungen auf die Schnittstelle mit Legacy-Code haben.
Im Vergleich zu einem regulären Allokator verursacht ein polymorpher Allokator einige geringfügige Kosten, wie z. B. den Speicheraufwand des Zeigers memory_resource (der höchstwahrscheinlich vernachlässigbar ist) und die Kosten für den Versand virtueller Funktionen für Zuordnungen. Das Hauptproblem ist wahrscheinlich die mangelnde Kompatibilität mit Legacy-Code, der keine polymorphen Allokatoren verwendet.
allocator<T>
Natur aus bestehen. Sie werden also einen Wert darin sehen, wenn Sie häufig Allokatoren verwenden.