在 C++ STL 容器对象上不调用 clear() 的内存泄漏

Memory Leaks without calling clear() on C++ STL container objects

假设我有一个 class Foo 定义如下。 如果我在~Foo()中没有bars.clear(),会不会导致内存泄露? 我想知道这一点,因为 bars 是一个对象字段(不是指针字段)所以当 ~Foo() 被调用时, [ 的析构函数=13=]std::vector 应该自动调用所以我想知道 std::vector 的析构函数是否会透明地调用 .clear( )与否。

    class Foo
    {
      private:
        std::vector<Bar*> bars;//object field

      ...
    };


    Foo::~Foo
    {
      //bars.clear();
    }

clear() 只是将向量重置为大小 0。它不会 delete 任何东西,如果向量 bars 中的 Bar* 需要删除,你有自己做。

std::vector::clear() 删除 std::vector 中的对象并将其 std::vector::size() 更改为零。如果您创建 std::vector,RAII 将负责资源释放过程,但您必须等到超出向量范围。如果在超出范围之前,您需要清理向量,您可以使用 std::vector::clear().

但在您的特殊情况下,您将指向对象的指针保留在 std::vector 内,因此 RAII 会删除指针但忽略指向指针的对象。因此,您必须在超出范围和 RAII 激活之前或在调用 std::vector::clear()

之前自行清理指向指针的对象

如果您希望通过调用 clear() 方法来保护自己免受内存泄漏,那么我不得不让您失望了。如果你使用带指针的向量,你需要做这样的事情:

std::vector<Bar*> bars;
bars.push_back(new Bar());
// some work with bars
//  ....
// end of bars usage:
// (probably inside ~Foo() )
for(int i=0; i<bars.size(); i++) delete bars[i];

根据您的经验水平和具体用例,您最好使用:

   std::vector<Bar> bars;

如果您想知道 std::vector<...>::clear() 方法是否从 vector 的析构函数中调用,那么答案是:可能但不一定而且它确实反正没关系。

如果您真的很好奇,您也许可以通过查看矢量容器模板的头文件来检查容器 class 的析构函数的作用。 std 库对象的实现细节是否对用户可见以及有多少实现细节在很大程度上取决于您使用的系统 运行。在工作中,我碰巧在 Solaris 10 机器上工作。这些机器上的标准库是 Hewlett Packard anno 1994 的实现,其中矢量模板使用的许多实际代码仍然可见:

~vector ()
{ 
  __destroy(__start, __finish); 
  __value_alloc_type va(__end_of_storage);
  va.deallocate(__start,__end_of_storage.data()-__start);
}
void clear()
{
  erase(begin(),end());
}
iterator erase (iterator first, iterator last)
{
  iterator i = copy(last, end(), first);
  iterator tmp = __finish;
  __finish = __finish - (last - first); 
  __destroy(i, tmp);
  return first;
}