Citazione scelta da cppreference:
Questo polimorfismo di runtime consente agli oggetti che utilizzano polymorphic_allocator di comportarsi come se usassero diversi tipi di allocatore in fase di esecuzione nonostante lo stesso tipo di allocatore statico
Il problema con gli allocatori "normali" è che cambiano il tipo di contenitore. Se vuoi un vector
con un allocatore specifico, puoi utilizzare il Allocator
parametro template:
auto my_vector = std::vector<int,my_allocator>();
Il problema ora è che questo vettore non è dello stesso tipo di un vettore con un allocatore diverso. Non è possibile passarlo a una funzione che richiede un vettore di allocatore predefinito, ad esempio, o assegnare due vettori con un diverso tipo di allocatore alla stessa variabile / puntatore, ad esempio:
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
Un allocatore polimorfico è un singolo tipo di allocatore con un membro che può definire il comportamento dell'allocatore tramite invio dinamico anziché tramite il meccanismo del modello. Ciò consente di avere contenitori che utilizzano un'allocazione specifica e personalizzata, ma che sono comunque di un tipo comune.
La personalizzazione del comportamento dell'allocatore viene eseguita assegnando all'allocatore 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
Il problema principale rimanente, a mio avviso, è che un std::pmr::
contenitore non è ancora compatibile con il std::
contenitore equivalente che utilizza l'allocatore predefinito. È necessario prendere alcune decisioni nel momento in cui si progetta un'interfaccia che funzioni con un contenitore:
- è probabile che il contenitore passato possa richiedere un'allocazione personalizzata?
- in caso affermativo, devo aggiungere un parametro modello (per consentire allocatori arbitrari) o devo imporre l'uso di un allocatore polimorfico?
Una soluzione modello consente qualsiasi allocatore, incluso un allocatore polimorfico, ma presenta altri inconvenienti (dimensione del codice generato, tempo di compilazione, codice deve essere esposto nel file di intestazione, potenziale ulteriore "contaminazione del tipo" che continua a spingere il problema all'esterno). Una soluzione di allocatore polimorfico d'altra parte impone che deve essere utilizzato un allocatore polimorfico . Ciò preclude l'utilizzo di std::
contenitori che utilizzano l'allocatore predefinito e potrebbe avere implicazioni per l'interfacciamento con il codice legacy.
Rispetto a un allocatore normale, un allocatore polimorfico ha alcuni costi minori, come l'overhead di archiviazione del puntatore memory_resource (che è molto probabilmente trascurabile) e il costo dell'invio di funzioni virtuali per le allocazioni. Il problema principale, in realtà, è probabilmente la mancanza di compatibilità con il codice legacy che non utilizza allocatori polimorfici.
allocator<T>
intrinsecamente. Quindi vedrai il valore in esso se usi frequentemente gli allocatori.