Hier ist die Dokumentation zu cppreference , hier ist der Arbeitsentwurf.
Ich muss zugeben, dass ich nicht verstanden habe, was der eigentliche Zweck ist polymorphic_allocator
und wann / warum / wie ich es verwenden soll.
Als Beispiel pmr::vector
hat der folgende Signatur:
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
Was macht das polymorphic_allocator
Angebot? Was bietet das std::pmr::vector
Angebot auch in Bezug auf das Altmodische std::vector
? Was kann ich jetzt tun, wo ich bis jetzt nicht konnte?
Was ist der eigentliche Zweck dieses Allokators und wann sollte ich ihn tatsächlich verwenden?
allocator<T>
Natur aus bestehen. Sie werden also einen Wert darin sehen, wenn Sie häufig Allokatoren verwenden.Antworten:
Auswahl Zitat aus cppreference:
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 denAllocator
Vorlagenparameter verwenden: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.
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 *
:Das verbleibende Hauptproblem ist meines Erachtens, dass ein Container mit dem Standard-Allokator
std::pmr::
immer noch nicht mit dem entsprechendenstd::
Container kompatibel ist . Sie müssen einige Entscheidungen treffen, wenn Sie eine Schnittstelle entwerfen, die mit einem Container funktioniert: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.
quelle
std::pmr::
sehr wahrscheinlich, dass das binäre Layout für Klassen unterschiedlich ist?reinterpret_cast
zwischen astd::vector<X>
undstd::pmr::vector<X>
, wenn du das fragst .std::pmr::
Container iststd::
mit dem Standard -Allokator immer noch nicht mit dem entsprechenden Container kompatibel . " Es ist auch kein Zuweisungsoperator von einem zum anderen definiert. Probieren Sie es im Zweifelsfall aus: godbolt.org/z/Q5BKev (Code ist nicht genau wie oben, da gcc / clang die polymorphen Zuordnungsklassen in einem "experimentellen" Namespace haben).template<class OtherA, std::enable_if< A can be constructed from OtherA > vector( vector<T, OtherA>&& )
Konstruktor. Ich war mir nicht sicher und wusste nicht, wo ich einen Compiler mit TS-kompatiblem pmr finden sollte.polymorphic_allocator
ist für einen benutzerdefinierten Allokator wiestd::function
für einen direkten Funktionsaufruf.Sie können einfach einen Allokator für Ihren Container verwenden, ohne zum Zeitpunkt der Deklaration entscheiden zu müssen, welcher. Wenn Sie also eine Situation haben, in der mehr als ein Allokator angemessen wäre, können Sie verwenden
polymorphic_allocator
.Vielleicht möchten Sie ausblenden, welcher Allokator zur Vereinfachung Ihrer Benutzeroberfläche verwendet wird, oder Sie möchten ihn für verschiedene Laufzeitfälle austauschen können.
Zuerst benötigen Sie Code, der einen Allokator benötigt, dann müssen Sie in der Lage sein, den verwendeten Code auszutauschen, bevor Sie den pmr-Vektor berücksichtigen.
quelle
Ein Nachteil von polymorphen Allokatoren ist, dass dies
polymorphic_allocator<T>::pointer
immer gerecht istT*
. Das heißt, Sie können sie nicht mit ausgefallenen Zeigern verwenden . Wenn Sie beispielsweise Elemente von avector
im gemeinsam genutzten Speicher platzieren und überboost::interprocess::offset_ptr
s darauf zugreifen möchten, müssen Sie dafür einen normalen alten nicht polymorphen Allokator verwenden.Obwohl Sie mit polymorphen Allokatoren das Zuordnungsverhalten variieren können, ohne den statischen Typ eines Containers zu ändern, begrenzen sie die Zuordnung .
quelle