A другой вопрос вдохновил на следующую мысль:
Имеет ли std::vector<T>
для перемещения всех элементов, когда он увеличивает свою емкость?
Насколько я понимаю, стандартное поведение заключается в том, что базовый распределитель запрашивает целый кусок нового размера, затем перемещает все старые элементы, затем уничтожает старые элементы и затем освобождает старую память.
Такое поведение представляется единственно возможным правильным решением с учетом стандартного интерфейса распределителя.Но мне было интересно, имеет ли смысл изменить распределитель, чтобы он предлагал функцию reallocate(std::size_t)
, которая возвращала бы pair<pointer, bool>
и могла бы отображаться на базовый realloc()
?Преимущество этого состоит в том, что в случае, если операционная система может просто расширить выделенную память, тогда никакого перемещения вообще не должно произойти.Логическое значение будет указывать, была ли перемещена память.
(std::realloc()
, возможно, не лучший выбор, потому что нам не нужно копировать данные, если мы не можем расширять. Поэтому на самом деле мы бы предпочли что-токак extend_or_malloc_new()
. Редактировать: Возможно, специализация на основе is_pod
позволит нам использовать фактический realloc
, включая его побитовую копию. Только не в общем.)
Это похоже на упущенную возможность.В худшем случае, вы всегда можете реализовать reallocate(size_t n)
как return make_pair(allocate(n), true);
, чтобы не было никаких штрафов.
Есть ли проблема, которая делает эту функцию неприемлемой или нежелательной для C ++?
Возможно, единственным контейнером, который может воспользоваться этим, является std::vector
, но опять же, это довольно полезный контейнер.
Обновление: небольшой пример для пояснения.Текущая resize()
:
pointer p = alloc.allocate(new_size);
for (size_t i = 0; i != old_size; ++i)
{
alloc.construct(p + i, T(std::move(buf[i])))
alloc.destroy(buf[i]);
}
for (size_t i = old_size; i < new_size; ++i)
{
alloc.construct(p + i, T());
}
alloc.deallocate(buf);
buf = p;
Новая реализация:
pair<pointer, bool> pp = alloc.reallocate(buf, new_size);
if (pp.second) { /* as before */ }
else { /* only construct new elements */ }