Как использовать std::allocator вместо realloc?

Допустим, я пишу собственный вектор, используя std::allocator обернуть new а также delete,

Когда количество элементов превышает емкость вектора, я бы хотел перераспределить буфер на что-то большее. Я могу легко добиться этого, позвонив realloc(), Я не хочу этого делать, потому что считал, что ответственность за распределение / освобождение должна лежать на распределителе.

Тем не менее, глядя на std::allocatorИнтерфейс, я не вижу, как я мог бы сделать перераспределение. Есть только методы для:

T* allocate( std::size_t n );
void deallocate( T* p, std::size_t n );

Должен ли я звонить allocator::allocate а потом allocator::deallocate вместо просто realloc? Это так эффективно? Должно быть что std::vector тоже хорошо. Почему std::allocator не предоставлять reallocate функционировать?

1 ответ

Решение

Допустим, я пишу собственный вектор, используя std::allocator для переноса new и delete.

В общем случае (исключая специализации для POD), я не думаю, что вы могли бы использовать realloc в любом случае. Произвольный объект, созданный в определенном месте памяти, может иметь внутренние указатели, указывающие на очень конкретные адреса по отношению к адресу, в котором он был создан. Простое перемещение (в смысле копирования байтов) может нарушить инварианты.

Таким образом, альтернатива, которую вы упоминаете, в целом необходима Вы должны были бы выделить новый массив, move (или, возможно, даже copy!) объекты на новое место, затем освободите старый массив. Конечно, это включает в себя более одного этапа, который может потерпеть неудачу - еще одна причина, почему вы не можете на самом деле reallocate в общем случае. Возможно, это причина того, что распределители никогда не имели такой функциональности в первом случае - для контейнеров на основе массива вы не можете использовать их вообще (хотя вы могли бы использовать их для специализаций POD).

Другие вопросы по тегам