Должен ли std :: vector * перемещать объекты при увеличении емкости? Или могут ли распределители «перераспределяться»?

другой вопрос вызвал следующую мысль:

Имеет ли 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 */ }

51
задан Community 23 May 2017 в 00:31
поделиться