Cytat wyboru z cppreference:
Ten polimorfizm w czasie wykonywania pozwala obiektom używającym polymorphic_allocator zachowywać się tak, jakby używały różnych typów alokatorów w czasie wykonywania pomimo identycznego statycznego typu alokatora
Problem z „zwykłymi” alokatorami polega na tym, że zmieniają one typ kontenera. Jeśli chcesz mieć vector
określony alokator, możesz skorzystać z Allocator
parametru szablonu:
auto my_vector = std::vector<int,my_allocator>();
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 .:
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
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 *
:
// 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
Główny pozostały problem, jak to widzę, polega na tym, że std::pmr::
kontener nadal nie jest zgodny z odpowiadającym mu std::
kontenerem korzystającym z domyślnego alokatora. Podczas projektowania interfejsu, który współpracuje z kontenerem, musisz podjąć pewne decyzje:
- czy jest prawdopodobne, że przekazany kontener może wymagać przydziału niestandardowego?
- jeśli tak, czy powinienem dodać parametr szablonu (aby umożliwić dowolne przydzielanie), czy też powinienem nakazać użycie alokatora polimorficznego?
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.
allocator<T>
nieodłączne problemy . Więc zobaczysz w tym wartość, jeśli często używasz alokatorów.