Требуется ли сохранить емкость при перемещении std :: vector?

Рассмотрим следующий код:

std::vector vec;
vec.reserve(500);
size_t cap = vec.capacity();

std::vector newVec = std::move(vec);
assert(cap == newVec.capacity());

Практически в любой реализации, с которой вы столкнетесь, это будет работать. Меня не волнует, что делают реализации. Я хочу знать, что стандарт требует. Будет ли переезд vector имеют ту же емкость, что и оригинал? Или актив будет срабатывать?

17

Решение

Глядя на стандарт, кажется, что ничего не требуется от конструктора перемещения, однако, как говорит @amaurea, было бы полностью нарушено назначение семантики перемещения, если бы конструктор перемещения попытался выделить или освободить память, поэтому я ожидал, что емкость оставаться неизменным во всех реализациях.


23.2.1 Общие требования к контейнерам

выражение

X u(a);
X u = a;

Утверждение / примечание до / после условия

Требуется: T CopyInsertable в X (см. ниже).
сообщение: u == a


Стандарт требует только, чтобы newVec == vec, Поскольку мощность не учитывается для std::vector::operator==, newVec не обязательно должны иметь такую ​​же емкость, как vec,

11

Другие решения

Стандартные требования C ++ 11 к конструктору перемещения для std::vector (Таблица 99 — Требования к контейнерам, учитываемые Распределителем):

X(rv)
X u(rv)
  • Перемещение конструкции распределителя не должно выходить через исключение
  • post: у вас должны быть те же элементы, что и rv имел до этой конструкции; значение get_allocator() должно быть таким же, как значение rv.get_allocator() до этой конструкции.
  • сложность: постоянная

Здесь нет требований / гарантии по мощности. Но мы можем сделать вывод, что постоянная сложность неявно отрицает любые перераспределения. И я не вижу ничего другого логический причина для изменения емкости, кроме перераспределения. Так и должно быть.

С другой стороны, если вектор с удалением пуст, совершенно законно просто игнорировать его и конструировать по умолчанию. Это все равно будет O (1), так как он не требует каких-либо конструкций для каждого элемента. (Благодаря Николь Болас по этому вопросу).

Также реализация может уменьшить емкость до размера, используя hint параметр std::allocator::allocate функция:

pointer allocate(size_type, allocator<void>::const_pointer hint = 0);

Использование hint не определено, но предназначено как помощь населению, если реализация того пожелает. Таким образом, какое-то изощренное решение может передать указатель на векторное хранилище как hint и использовать realloc на это уменьшить емкость.

Заключение: выглядит как стандарт, не гарантирует сохранение грузоподъемности при движении std::vector, хранилище потенциально может быть сокращено.

9

По вопросам рекламы [email protected]