1

语境

我正在尝试实现我的std::vector模板类版本。向量包含模板参数的动态数组T

_vec = new T[n];

显然T可以是任何类型,指针、类、原始类型。当调用v.resize(4)一个大小的向量时,6它显然应该按照本规范删除动态数组的最后 2 个元素(不重新分配数组) :

如果 n 小于当前容器大小,则内容将减少到它的前 n 个元素,删除超出的那些(并销毁它们)。

通过破坏我的意思是,我认为 std 库意味着调用对象的析构函数,或者如果它是包括指针在内的任何其他原始类型,则简单地释放内存空间。

问题:是否有可能(如果有,如何)销毁动态分配的数组中的模板元素而不解除分配和重新分配它?

我尝试了什么?好吧,我真的不知道从哪里开始:

  • 显然你不应该delete在原始类型上调用 a 。
  • 您可以在对象上显式调用析构函数,但如果不是对象,这将不起作用T
  • 我想只是减少​​内部_size计数器(以便将来push_back会覆盖元素),但这不会立即调用对象的析构函数。
4

3 回答 3

2

在实现 时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()

这些函数在预分配的内存中构造和解构对象,但它们本身并不管理内存。

于 2013-04-03T09:01:59.700 回答
1

new T[n]不是您想要的,因为这已经创建了 type 的n 对象T,但您只想为最多type 的对象分配内存nT

您可能需要阅读有关placement-new 语法和placement-delete 语法的内容。维基百科

于 2013-04-03T08:35:51.730 回答
0

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

他们使用带有特殊标志的简单调度,可以使用一些特征类来计算。

于 2013-04-03T09:06:05.020 回答