stl +内存管理问题

Posted

技术标签:

【中文标题】stl +内存管理问题【英文标题】:stl + memory management question 【发布时间】:2011-06-08 19:38:39 【问题描述】:

例如,我有下一个代码:

#include <set>
using namespace std;

struct SomeStruct 

    int a;
;

int main ()

    set<SomeStruct *> *some_cont = new set<SomeStruct *>;
    set<SomeStruct *>::iterator it;
    SomeStruct *tmp;

    for (int i = 0 ; i < 1000; i ++)
    
        tmp = new SomeStruct;
        tmp->a = i;
        some_cont->insert(tmp);
    

    for (it = some_cont->begin(); it != some_cont->end(); it ++)
    
        delete (*it);
    

    some_cont->clear(); // <<<<THIS LINE
    delete some_cont;
    return 0;

是否需要在删除 some_cont 之前调用“THIS LINE”以避免内存泄漏或析构函数会被自动调用?

【问题讨论】:

顺便说一下,你的typedef不应该有() 您应该知道,您所拥有的是一些老式的 C 风格代码,而不是用 C++ 编写的正确方法。 【参考方案1】:

你不需要调用它,析构函数肯定会被调用。

【讨论】:

【参考方案2】:

不,在销毁之前不需要清除集合。

请注意,很少需要手动分配std::set(或任何标准容器)。你最好把它放在自动存储中并让 C++ 为你处理清理工作:

所以不是

set<SomeStruct *> *some_cont = new set<SomeStruct *>;

使用

set<SomeStruct *> some_cont;

然后将所有some_cont-&gt;更改为some_cont.并删除delete some_cont(当main自动退出时容器将被销毁。

这样做的好处是:

    你不需要记得删除容器,并且 您无需预先进行昂贵的内存分配。

将东西放入自动存储中也更加符合 C++ 习惯。

【讨论】:

【参考方案3】:

不,您不需要在销毁 set 之前明确清除 set

OTOH,您确实遇到了许多其他问题,从糟糕的(类似 Java 的)设计到不正确的语法、缺少运算符到大量潜在的内存泄漏。虽然某些设计在 Java 或 C# 中可能有意义,但在 C++ 中这是一个真的糟糕的想法。一旦我们摆脱了最严重的问题,我们剩下的就是这样的:

#include <set>

struct SomeStruct 

    int a;
    SomeStruct(int i) : a(i) 
    bool operator<(SomeStruct const &other) const  return a < other.a; 
;

int main ()

    std::set<SomeStruct> some_cont;

    for (int i = 0 ; i < 1000; i ++)
    
        SomeStruct tmp(i);
        some_cont.insert(tmp);
    
    return 0;

【讨论】:

我什至会避免使用tmp (: @Kiril:我可能也会这样做——但我试图尽可能多地保留原件,同时仍然至少有一半是合理的。其他变化是(IMO)必不可少的;那个是可取的,但可选的。 是的,但是我的对象的生命周期以不同的函数开始和结束,所以我需要使用分配和释放。 @Oleg:不是真的。当您将某些东西插入到集合中时,它会被复制到集合中,然后集合拥有该对象的(副本)。除非您先将其从集合中删除,否则它将具有集合的生命周期。存储在set 中的对象需要具有可比性。如果您不关心排序(或至少是唯一性,这仍然取决于比较),您可能需要其他容器。 这听起来有点像func1func2 作为同一个类的成员可能有意义,而set(或vector)作为同一个类的成员,所以容器及其内容在父对象的生命周期中存在。【参考方案4】:

不,不是,这将在集合的析构函数中自动完成。

【讨论】:

【参考方案5】:

STL 容器会自动释放它们拥有的所有内存。因此,在您的情况下,分配给存储 SomeStruct* 的位置将由 set 的析构函数释放。请注意,set 的析构函数不会调用 SomeStruct 的任何析构函数,因此最好迭代它们以自己删除它们。

【讨论】:

你错了——调用 set 的析构函数将调用 all SomeStruct的析构函数,如果它们被分配在堆栈上的话。需要显式删除所有已分配的SomeStruct 对象与set 的析构函数无关。 @Kiril:但它们没有分配在堆栈上。它们是在 1000 次 for 循环中使用 new 分配的。在该示例中,所有SomeStructs 都不会被释放。 @Peter - 是的,你是对的,我不说别的了。我是说,@danta 关于“请注意 set 的析构函数不会调用 SomeStruct 的任何析构函数”是错误的——释放内存,分配在堆上,与 set 的析构函数无关案例,对吧? 如果我没记错的话,boost 有一些拥有所有权的容器。因此,如果您插入 SomeStruct 指针,它将负责删除它。我只是想提一下,stl 容器不会做这样的事情。 有可能,我不知道。听起来像是某种容器,使用auto_ptr 智能指针。但是,set 不是 boost 容器,它调用插入到其中的所有对象(注意 - 对象,而不是指针)的析构函数。

以上是关于stl +内存管理问题的主要内容,如果未能解决你的问题,请参考以下文章

stl内存管理allocator(转)

C++ STL 内存管理:堆栈还是堆?

c++ stl复制函数正确的内存管理

STL的内存分配器

SGI STL内存管理

STL中的内存分配器原理