Есть разница между емкостью и размером. С учетом std::vector<T> v;
Вектор выделил память для v.capacity()
элементов. Но только в первых v.size()
местах содержатся построенные T
объекты.
Итак, v.reserve(1000)
для пустого вектора не вызовет никаких дополнительных конструкторов. vec.resize(2)
в вашем примере уничтожает последний элемент, а vec[2]
теперь пустое место в памяти, но память все еще принадлежит vec
.
Я думаю, что ваше распределение выглядит как buffer = new T[newSize];
. Это не то, как работает std::vector
, что не позволяет Ts
, которые не имеют конструкторов по умолчанию. Возможно, вы этого не понимали, но всякий раз, когда вы получаете кусок памяти, он уже содержит объекты, пусть это будет T x;
или даже new double[newSize];
, который возвращает массив значений типа double (хотя их конструкторы пусты).
Существует только один способ получить пригодную для использования неинициализированную память в C ++, а именно выделить chars
. Это связано с строгим правилом алиасинга. Также существует (должен | быть) способ явного вызова конструктора в этой памяти, т. Е. Как создать там объект. Вектор использует то, что называется размещение новых , что делает именно это. Распределение тогда просто buffer = new char[newSize*sizeof(T)];
, которое не создает никаких объектов.
Время жизни объектов управляется этим новым оператором размещения и явными вызовами деструкторов.
emplace_back(arg1,arg2)
может быть реализовано как {new(buffer + size) T(arg1,arg2);++size;}
. Обратите внимание, что просто делать buffer[size]=T(arg1,arg2);
неправильно и UB. operator=
ожидает, что левый размер (*this
) уже существует.
Если вы хотите уничтожить объект, например, с помощью pop_back
, вы должны сделать
buffer[size].~T();--size;
. Это одно из немногих мест, где вы должны явно вызывать деструктор.