другой вопрос вызвал следующую мысль:
Имеет ли std :: vector
перемещать все элементы при увеличении своей емкости?
Насколько я понимаю, стандартное поведение - это то, что базовый распределитель запрашивает весь кусок нового размера, затем перемещает все старые элементы, а затем уничтожить старые элементы, а затем освободить старую память.
Такое поведение кажется единственно возможным правильным решением с учетом стандартного интерфейса распределителя. Но мне было интересно, имеет ли смысл изменить распределитель, чтобы он предлагал функцию reallocate (std :: size_t)
, которая возвращала бы пару pair
и могла бы отображать на лежащий в основе realloc ()
? Преимущество этого состоит в том, что в том случае, если ОС может просто расширить выделенную память, никакого перемещения вообще не должно происходить. Логическое значение указывает, переместилась ли память.
( std :: realloc ()
, возможно, не лучший выбор, потому что нам не нужно копировать данные, если мы не можем расширить. Так что на самом деле мы бы предпочли что-то вроде extension_or_malloc_new ()
. Редактировать: Возможно, специализация на основе is_pod
-trait позволит нам использовать реальный реаллок
, включая его побитовую копию. Только не в общем.)
Похоже, это упущенная возможность. В худшем случае вы всегда можете реализовать 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 pp = alloc.reallocate(buf, new_size);
if (pp.second) { /* as before */ }
else { /* only construct new elements */ }