9

在 Accelerated C++ 的第 11 章中,作者介绍了一个 Vector 类,它使用数组来模拟 std::vector 的行为。他们使用分配器类来处理内存管理。该函数的uncreate作用是销毁数组的每个元素并释放为数组分配的空间:

template <class T> void Vec<T>::uncreate() {
  if (data) {

  // destroy (in reverse order) the elements that were constructed 
  iterator it = avail;
  while (it != data)
    alloc.destroy(--it);

  // return all the space that was allocated
  alloc.deallocate(data, limit - data); 
  }

  // reset pointers to indicate that the Vec is empty again 
  data = limit = avail = 0;
}

显然我们需要释放分配的空间。但我不清楚为什么我们也需要销毁单个元素。如果我们只释放内存而不破坏单个元素会发生什么?

4

2 回答 2

13

原因是它可能会给你带来麻烦。C++ 标准第 3.8 章(对象生命周期)的第 4 段解释了原因(强调我的):

程序可以通过重用对象占用的存储空间或通过显式调用具有非平凡析构函数的类类型对象的析构函数来结束任何对象的生命周期。对于具有非平凡析构函数的类类型的对象,在重用或释放对象占用的存储空间之前,程序不需要显式调用析构函数;但是,如果没有显式调用析构函数,或者如果没有使用删除表达式 (5.3.5) 来释放存储,则不应隐式调用析构函数以及依赖于析构函数产生的副作用的任何程序具有未定义的行为。

这意味着可以在被具有琐碎析构函数(*)的对象或根本没有析构函数(ints诸如此类)的对象占用的内存上执行此操作。但是当内存包含需要在析构函数中做一些工作的类的对象时(如关闭网络连接或文件、刷新缓冲区、释放内存),您将泄漏资源(并且正式地按照标准,调用未定义的行为)。

(*) 如果析构函数是编译器生成的,不是虚拟的,并且它所属的类的所有非静态成员和直接基类都具有平凡的析构函数,那么它就是平凡的。

于 2013-08-06T10:50:50.120 回答
8

销毁单个元素可确保调用它们的析构函数,因此它们有机会释放它们拥有的任何资源。简单地释放内存不会调用放置在该内存中的对象的析构函数。

于 2013-08-06T10:51:43.787 回答