在c++ STL容器对象上不调用clear()而导致内存泄漏

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

本文关键字:泄漏 内存 clear 调用 STL c++ 对象      更新时间:2023-10-16

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

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

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

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

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

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

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

如果您希望通过调用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的析构函数内部调用,那么答案是:可能,但不一定,而且这真的无关紧要。

如果你真的很好奇,你可以通过查看vector容器模板的头文件来检查容器类的析构函数是做什么的。std库对象的实现细节是否以及有多少对用户可见高度依赖于您所运行的系统。在工作中,我碰巧使用Solaris 10机器。这些机器上的std库是Hewlett Packard 1994年的实现,其中vector模板使用的许多实际代码仍然可见:

~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;
}