Как использовать 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?


person Trevor Hickey    schedule 02.08.2016    source источник
comment
Почему std :: allocator не предоставляет функцию перераспределения? Это частично рассматривается в этот вопрос.   -  person sjrowlinson    schedule 02.08.2016
comment
[FYI] isocpp.org/wiki/faq/freestore-mgmt#realloc -и-продлить   -  person NathanOliver    schedule 02.08.2016
comment
@NathanOliver В конце говорится, что в C ++ лучший способ справиться с перераспределением - использовать контейнер стандартной библиотеки, такой как vector, и позволить ему расти естественным образом., Что является отправной точкой этого вопроса ...   -  person Ami Tavory    schedule 02.08.2016
comment
@AmiTavory И все идет по кругу;) Просто указываю OP, что смешивание new и realloc - не очень хорошая идея.   -  person NathanOliver    schedule 02.08.2016
comment
@NathanOliver Вы правы, и комментарий действительно уместен. Извините, если я ошибочно произвел впечатление, что думал, что это не так.   -  person Ami Tavory    schedule 02.08.2016
comment
Без проблем. Это ... в конце заставило меня подумать, что с этим что-то не так. Но не беспокойтесь.   -  person NathanOliver    schedule 02.08.2016
comment
Стоит отметить, что, хотя realloc работает на более низком уровне, чем, скажем, std::vector емкость, они оба делают в основном одно и то же, и реализация перераспределения самостоятельно с использованием комбинации allocate, deallocate и перемещение должно быть столь же эффективным (вероятно, в целом более эффективно, так как мы можем давать подсказки в форме емкости): realloc в конце концов не творит магию.   -  person Konrad Rudolph    schedule 02.08.2016


Ответы (1)


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

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

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

person Ami Tavory    schedule 02.08.2016