Подтвердить что ты не робот

Почему std:: allocator является шаблоном?

Задача распределителя - получить "сырую" память через свой метод allocate. То, что вызывающий объект создает в памяти, возвращенной распределителем, не имеет отношения к распределителю (правильно?). Итак, почему шаблон std::allocator, когда это только добавляет лишнюю сложность? Что делает распределитель на самом деле с информацией этого типа? Почему он должен знать тип объекта, для которого предназначена память? Я предполагаю, что есть какая-то очевидная причина, по которой мне не хватает, и в чем причина?

4b9b3361

Ответ 1

Ну, std::allocator и сама концепция Allocator были изобретены для решения таких проблем, как ближний и дальний указатели, или, как правило, указатели на разные адресные пространства. И они справляются с этим... адекватно. Распределитель определяет используемый тип указателя.

Они также могут использоваться для работы с разными распределителями памяти, хотя количество шаблонов для этого несколько ошеломляет.

И, наконец, контейнер, поддерживающий распределитель, может сочетаться с распределителем, использующим преимущества, которые предоставляют вспомогательный распределитель для дочерних элементов, что может помочь уменьшить накладные расходы.


Первая точка в настоящее время в основном устарела, хотя ее можно использовать со второй точкой, чтобы иметь контейнер с отображением-адресом-инвариантом в сегменте разделяемой памяти или файл.

Вторая точка может использоваться для использования специализированных распределителей, хотя интерфейс для этого не очень хорош. Пример, когда я использовал его для взломать безопасный std::basic_string.

И последний пункт редко используется.


Единственным огромным недостатком концепции Allocator, как определено, является тот факт, что он использует шаблон. Все использование уже проходит через std::allocator_traits<Allocator>, поэтому оно просто приводит к тому, что типы невольно становятся почти одинаковыми, не было ли аргумента шаблона для распределителя.
А также к большому дублированному коду для надлежащего переподключения распределителя.

Ответ 2

На ум приходит умение. Различные типы имеют разные требования к выравниванию, ячейка памяти, которая хороша для массива char, может быть неприемлемой для double (для которой обычно требуются 8-байтовые выровненные адреса).

OTOH, следует отметить, что malloc решает эту проблему, предоставляя память, которая имеет правильное выравнивание для самых строгих встроенных типов, что обычно является достаточно хорошим решением для универсального распределителя.