контекст
Я пытаюсь реализовать мою версию std::vector
шаблон класса. Вектор содержит динамический массив аргумента шаблона T
:
_vec = new T[n];
очевидно T
может быть любого типа, указатели, классы, примитивные типы. Когда один звонок v.resize(4)
на вектор размера 6
очевидно, он должен удалить последние 2 элемента динамического массива (без перераспределения массива) после эта спецификация:
Если n меньше текущего размера контейнера, содержимое сокращается до его первых n элементов, удаляя те, которые находятся за ними (и уничтожая их).
От разрушающий Я имею в виду, и я думаю, что библиотека std означает вызов деструктора для объекта или просто освобождение пространства памяти, если это любой другой примитивный тип, включая указатели.
Вопрос: Возможно ли (и если да, то как) уничтожить элементы шаблона в динамически распределенном массиве без его освобождения и перераспределения?
Что я пробовал? Ну, я искренне не знаю, с чего начать
delete
на примитивных типах. T
это не объект. _size
счетчик (так что будущее push_back
элементы будут перезаписаны), но это не сразу вызовет деструктор для объекта.Когда вы реализуете vector
Вы, вероятно, хотите разделить управление хранилищем и управление объектами.
Хранение управляется с помощью allocator::allocate(size_type n)
а также allocator::deallocate(pointer p, size_type n)
которые обычно реализуются как return ::operator new(n * sizeof (T));
а также ::operator delete(p);
соответственно.
Эти функции выделяют и освобождают память, но не вызывают конструкторы или деструкторы для объектов, содержащихся в этой памяти.
Время жизни объекта управляется с помощью allocator::construct(U* p, Args&&... args);
а также allocator::destroy(U* p);
которые обычно реализуются как ::new((void *)p) U(std::forward<Args>(args)...);
а также p->~U()
соответственно.
Эти функции создают и деконструируют объекты в предварительно выделенной памяти, но сами не управляют памятью.
new T[n]
это не то, что вы хотите, потому что это уже создаст n
объекты типа T
, но вы хотите только выделить объем памяти до n
объекты типа T
,
Вы можете прочитать о новом синтаксисе размещения и синтаксисе размещения-удаления. Википедия
FredOverflow прав насчет размещения объектов.
В соответствии с вашим вопросом, все, что вам нужно сделать, это просто отличить объекты от не-объектов (скаляры). Есть реальный код от <xmemory>
в выпуске Visual Studio 2010:
template<class _Alloc> inline void _Destroy_range(
typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al);
template<class _Alloc> inline void _Destroy_range(
typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al,
_Nonscalar_ptr_iterator_tag); // Object overload
template<class _Alloc> inline void _Destroy_range(
typename _Alloc::pointer _First, typename _Alloc::pointer _Last, _Alloc& _Al,
_Scalar_ptr_iterator_tag); // Non-object overload
Они используют простую диспетчеризацию со специальным флагом, который может быть вычислен с использованием некоторого класса черт.