Вибір із cppreference:
Цей поліморфізм часу виконання дозволяє об'єктам, що використовують polymorphic_allocator, поводитись так, ніби вони використовували різні типи алокаторів під час виконання, незважаючи на ідентичний тип статичного розподільника
Проблема з "звичайними" розподільниками полягає в тому, що вони змінюють тип контейнера. Якщо ви хочете мати vector
певний розподільник, ви можете скористатися Allocator
параметром шаблону:
auto my_vector = std::vector<int,my_allocator>();
Проблема зараз полягає в тому, що цей вектор не є тим самим типом, як вектор з іншим розподільником. Ви не можете передати його функції, яка вимагає, наприклад, вектора-розподільника за замовчуванням, наприклад, або призначити два вектори з іншим типом алокатора до тієї ж змінної / покажчика, наприклад:
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
Поліморфний алокатор - це єдиний тип алокатора з членом, який може визначати поведінку алокатора за допомогою динамічної диспетчеризації, а не через механізм шаблону. Це дозволяє мати контейнери, які використовують специфічне, індивідуальне розподілення, але все ще є загальним типом.
Налаштування поведінки алокатора здійснюється шляхом надання алокатора 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
Як я бачу, головне питання, що std::pmr::
контейнер все ще не сумісний з еквівалентним std::
контейнером, використовуючи розподільник за замовчуванням. Вам потрібно прийняти деякі рішення під час проектування інтерфейсу, який працює з контейнером:
- чи ймовірно, що контейнер, переданий у контейнер, може вимагати спеціального виділення?
- якщо так, чи слід додати параметр шаблону (щоб дозволити довільні алокатори) чи маю намір використовувати поліморфний розподільник?
Рішення шаблону дозволяє використовувати будь-який розподільник, включаючи поліморфний розподільник, але має й інші недоліки (згенерований розмір коду, час компіляції, код повинен бути викритий у файлі заголовка; потенціал для подальшого "типу забруднення", який продовжує висувати проблему назовні). Рішення поліморфного алокатора, з іншого боку, наказує, що необхідно використовувати поліморфний алокатор . Це виключає використання std::
контейнерів, які використовують розподільник за замовчуванням, і це може мати наслідки для взаємодії зі застарілим кодом.
Порівнюючи зі звичайним алокатором, поліморфний алокатор має деякі незначні витрати, такі як накладні витрати вказівника пам'яті_ресурсу (що, швидше за все, незначно) та вартість відправки віртуальної функції на розподіли. Насправді, головна проблема - це, мабуть, відсутність сумісності із застарілим кодом, який не використовує поліморфні розподільники.
allocator<T>
є у них. Тож ви побачите в ньому цінність, якщо ви часто використовуєте розподільники.