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->
更改为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
中的对象需要具有可比性。如果您不关心排序(或至少是唯一性,这仍然取决于比较),您可能需要其他容器。
这听起来有点像func1
和func2
作为同一个类的成员可能有意义,而set
(或vector
)作为同一个类的成员,所以容器及其内容在父对象的生命周期中存在。【参考方案4】:
不,不是,这将在集合的析构函数中自动完成。
【讨论】:
【参考方案5】:STL 容器会自动释放它们拥有的所有内存。因此,在您的情况下,分配给存储 SomeStruct* 的位置将由 set 的析构函数释放。请注意,set 的析构函数不会调用 SomeStruct 的任何析构函数,因此最好迭代它们以自己删除它们。
【讨论】:
你错了——调用 set 的析构函数将调用 allSomeStruct
的析构函数,如果它们被分配在堆栈上的话。需要显式删除所有已分配的SomeStruct
对象与set
的析构函数无关。
@Kiril:但它们没有分配在堆栈上。它们是在 1000 次 for 循环中使用 new
分配的。在该示例中,所有SomeStruct
s 都不会被释放。
@Peter - 是的,你是对的,我不说别的了。我是说,@danta 关于“请注意 set 的析构函数不会调用 SomeStruct 的任何析构函数”是错误的——释放内存,分配在堆上,与 set
的析构函数无关案例,对吧?
如果我没记错的话,boost 有一些拥有所有权的容器。因此,如果您插入 SomeStruct 指针,它将负责删除它。我只是想提一下,stl 容器不会做这样的事情。
有可能,我不知道。听起来像是某种容器,使用auto_ptr
智能指针。但是,set
不是 boost
容器,它调用插入到其中的所有对象(注意 - 对象,而不是指针)的析构函数。以上是关于stl +内存管理问题的主要内容,如果未能解决你的问题,请参考以下文章