A другой вопрос вдохновил следующую мысль:
Нужно ли std::vector<T>
перемещать все элементы при увеличении его емкости?
Насколько я понимаю, стандартное поведение заключается в том, что базовый распределитель запросит весь фрагмент нового размера, затем переместит все старые элементы, затем уничтожит старые элементы и затем освободит старую память.
Это поведение является единственным возможным правильным решением, учитывая стандартный интерфейс распределителя. Но мне было интересно, было бы целесообразно внести поправки в распределитель, чтобы предложить функцию reallocate(std::size_t)
, которая вернула бы pair<pointer, bool>
и могла бы отобразиться в базовый realloc()
? Преимущество этого заключалось бы в том, что в случае, если ОС фактически может просто расширить выделенную память, то никакое перемещение не должно происходить вообще. Логическое значение указывает, перемещена ли память.
(std::realloc()
, возможно, не самый лучший выбор, потому что нам не нужно копировать данные, если мы не можем продлить. Поэтому на самом деле нам бы хотелось получить что-то вроде extend_or_malloc_new()
. Edit: Возможно, is_pod
- специализированная специализация позволила бы нам использовать фактический realloc
, включая его побитую копию. Просто не в общем.)
Кажется, упущенная возможность. В худшем случае вы всегда можете реализовать reallocate(size_t n)
как return make_pair(allocate(n), true);
, поэтому не было бы никакого штрафа.
Есть ли какая-либо проблема, которая делает эту функцию неприемлемой или нежелательной для С++?
Возможно, единственным контейнером, который может воспользоваться этим, является 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 */ }