Oto dokumentacja dotycząca cppreference , tutaj jest robocza wersja robocza.
Muszę przyznać, że nie rozumiałem, jaki jest prawdziwy cel polymorphic_allocator
i kiedy / dlaczego / jak mam go używać.
Na przykład pmr::vector
ma następujący podpis:
namespace pmr {
template <class T>
using vector = std::vector<T, polymorphic_allocator<T>>;
}
Co polymorphic_allocator
oferuje ta oferta? Co std::pmr::vector
oferuje również w odniesieniu do staromodnych std::vector
? Co mogę teraz zrobić, czego nie mogłem zrobić do tej pory?
Jaki jest prawdziwy cel tego podzielnika i kiedy właściwie powinienem go używać?
allocator<T>
nieodłączne problemy . Więc zobaczysz w tym wartość, jeśli często używasz alokatorów.Odpowiedzi:
Cytat wyboru z cppreference:
Problem z „zwykłymi” alokatorami polega na tym, że zmieniają one typ kontenera. Jeśli chcesz mieć
vector
określony alokator, możesz skorzystać zAllocator
parametru szablonu:Problem polega teraz na tym, że ten wektor nie jest tego samego typu, co wektor z innym alokatorem. Nie można go przekazać do funkcji, która wymaga na przykład domyślnego wektora alokatora, ani przypisać dwóch wektorów z innym typem alokatora do tej samej zmiennej / wskaźnika, np .:
Alokator polimorficzny to pojedynczy typ alokatora z elementem, który może definiować zachowanie alokatora poprzez dynamiczne wysyłanie, a nie poprzez mechanizm szablonu. Pozwala to na posiadanie kontenerów, które używają określonej, dostosowanej alokacji, ale które są nadal powszechnego typu.
Dostosowanie zachowania podzielnika odbywa się poprzez nadanie alokatorowi
std::memory_resource *
:Główny pozostały problem, jak to widzę, polega na tym, że
std::pmr::
kontener nadal nie jest zgodny z odpowiadającym mustd::
kontenerem korzystającym z domyślnego alokatora. Podczas projektowania interfejsu, który współpracuje z kontenerem, musisz podjąć pewne decyzje:Rozwiązanie szablonowe pozwala na zastosowanie dowolnego alokatora, w tym alokatora polimorficznego, ale ma inne wady (rozmiar wygenerowanego kodu, czas kompilacji, kod musi być ujawniony w pliku nagłówkowym, możliwość dalszego „zanieczyszczenia typu”, co powoduje dalsze wypychanie problemu na zewnątrz). Polimorfizmu roztwór podzielnik z drugiej strony, który dyktuje polimorficzny podzielnik muszą być użyte. To wyklucza używanie
std::
kontenerów, które używają domyślnego alokatora i mogą mieć konsekwencje dla interakcji ze starszym kodem.W porównaniu ze zwykłym alokatorem, polimorficzny alokator ma pewne drobne koszty, takie jak narzut pamięci wskaźnika memory_resource (który jest najprawdopodobniej nieistotny) oraz koszt wysyłania funkcji wirtualnej do alokacji. Tak naprawdę głównym problemem jest prawdopodobnie brak kompatybilności ze starszym kodem, który nie używa alokatorów polimorficznych.
źródło
std::pmr::
klas będzie prawdopodobnie inny?reinterpret_cast
między astd::vector<X>
istd::pmr::vector<X>
, jeśli o to pytasz.std::pmr::
kontener nadal nie jest zgodny z równoważnymstd::
kontenerem korzystającym z domyślnego alokatora" . Nie ma też zdefiniowanego operatora przypisania z jednego do drugiego. W razie wątpliwości wypróbuj to: godbolt.org/z/Q5BKev (kod nie jest dokładnie taki, jak powyżej, ponieważ gcc / clang mają polimorficzne klasy alokacji w „eksperymentalnej” przestrzeni nazw).template<class OtherA, std::enable_if< A can be constructed from OtherA > vector( vector<T, OtherA>&& )
konstruktora. Byłem niepewny i nie wiedziałem, gdzie znaleźć kompilator zgodny z protokołem pmr zgodnym z TS.polymorphic_allocator
jest do niestandardowego alokatora, podobnie jakstd::function
do bezpośredniego wywołania funkcji.Po prostu pozwala na użycie podzielnika z kontenerem bez konieczności decydowania w momencie deklaracji, który z nich. Więc jeśli masz sytuację, w której więcej niż jeden podzielnik byłby odpowiedni, możesz użyć
polymorphic_allocator
.Może chcesz ukryć, który alokator jest używany do uproszczenia interfejsu, a może chcesz mieć możliwość zamiany go na różne przypadki uruchomieniowe.
Najpierw potrzebujesz kodu, który wymaga alokatora, a następnie musisz mieć możliwość zamiany używanego, przed rozważeniem wektora pmr.
źródło
Wadą alokatorów polimorficznych jest to, że
polymorphic_allocator<T>::pointer
zawsze są sprawiedliweT*
. Oznacza to, że nie możesz ich używać z fantazyjnymi wskazówkami . Jeśli chcesz zrobić coś takiego, jak umieszczenie elementów avector
we współdzielonej pamięci i dostęp do nich przezboost::interprocess::offset_ptr
s , musisz użyć do tego zwykłego, starego niepolimorficznego alokatora.Tak więc, chociaż alokatory polimorficzne pozwalają na zróżnicowanie zachowania alokacji bez zmiany statycznego typu kontenera, ograniczają to, czym jest alokacja .
źródło