为什么在此代码中调用析构函数?

时间:2014-02-21 06:57:06

标签: c++ data-structures dynamic-arrays

我正在阅读关于如何实现ArrayList的数据结构书籍,并且我有以下代码用于擦除功能:

template <typename T>
void ArrayList<T>::erase(int index) {

    //Delete the element whose index is "index"
    //Throw illegalIndex exception if no such element 
    checkIndex(index);



    std::copy(dynArr+ index + 1, dynArr + listSize, dynArr + index);

    dynArr[--listSize].~T(); //invoke destructor


}

析构函数定义为:

template<typename T>
ArrayList<T>::~ArrayList() {


delete [] dynArr;


}

我对那到底发生了什么感到困惑。当需要删除整个数组时,析构函数不是就在那里删除吗?

1 个答案:

答案 0 :(得分:2)

调用T的析构函数(不是ArrayList<T>的析构函数),可能是因为T类型的对象是在预分配的数组上创建的,而不是使用特殊的placement new operator在堆上单独创建的

因此当删除一个时,不需要释放任何内存但是你想调用析构函数以便清除状态

placement new运算符允许构造一个给定内存中地址的对象。这允许库(例如std :: vector)为将来的构造分配一块内存。并使用placement new运算符在该块的特定位置构建类实例:void* operator new (std::size_t size, void* ptr) throw();

但是当你想删除一个对象时,你不能delete它,因为它没有内存,但你仍然会调用析构函数,因此它会清理它自己的状态。 AFAIK 这是唯一直接调用dtor的用例

修改 解释为什么在最后一个对象而不是索引上调用析构函数:

std :: copy将使用它们的赋值运算符“复制”对象,如下所示:

template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
   while (first!=last) {
      *result = *first;
      ++result; ++first;
   }
   return result;
}

因此,对象的operator =将被多次调用。 位置索引处的对象将被写入位置索引+ 1处的对象。您希望正确的分配实现既可以释放自己的资源,也可以制作目标资源的精确副本。 完成此操作后,最终得到一个正确的数组,其中最后两个元素是彼此的精确副本,并使用析构函数清理最后一个元素。

注意:考虑到c ++ 11移动语义而不是std :: copy(如boost move算法boost::move),可能会提高性能。

注意2:如果您在某个位置&gt;索引处持有指向列表中元素的指针,则在更改此类别后,它将指向错误的元素。