我想在Obj
中存储10 objList
个对象,但我不知道在这种情况下何时适当使用delete
。如果我在下面代码中注明的行中使用delete Obj;
,Obj
是否仍会存储在objList
中?
struct Obj {
int u;
int v;
};
vector<Obj> objList;
int main() {
for(int i = 0; i < 10; i++) {
Obj *obj = new Obj();
obj->u = i;
obj->v = i + 1;
objList.push_back(*obj);
// Should i use "delete Obj;" here?
}
}
答案 0 :(得分:9)
是的,你应该。
您的计划中的每个delete
都应该有相应的new
。
但您的程序不需要动态分配:
Obj obj;
obj.u = i;
obj.v = i + 1;
objList.push_back(obj);
此外,您的语法错误 - objList.push_back(*Obj); // should be *obj, not *Obj
答案 1 :(得分:9)
您在new
堆上创建的任何对象都需要delete
清除。在您的代码中,您实际上是在副本中存储副本。
objList.push_back(*Obj);
这条线的步骤是:
Obj
)你不需要在堆上创建这个初始的Obj,就像@Luchian Grigore指出的那样,分配本地的堆栈就足够了。
Obj obj;
objList.push_back(obj);
您不需要在集合中的副本上调用delete,当您删除元素时,STL集合将自己处理此内存,但您仍需要删除原始堆分配的对象。
如果您按std::shared_ptr
存储对象会更好。这样,当删除对Obj的所有引用时,将调用delete。
std::vector< std::shared_ptr< Obj > > vec;
vec.push_back( std::make_shared( new Obj() ) );
答案 2 :(得分:3)
想想会发生什么:
在循环中,您将创建一个新的Obj实例并为其指定一些值。这个实例是在你的堆上创建的 - 因此你必须在之后释放它。当你将实例添加到向量时,你会隐含地创建它的副本 - 因为你有一个对象的向量,而不是指针。因此,矢量保留了自己的Obj副本。您可以安全地删除您的Obj实例。
顺便说一句:
对象x; x.u = i; x.v = i + 1; objList.push_back(X);
也可以
您应该阅读一些有关智能指针和智能指针容器的文章。例如。 boost :: scoped_ptr,boost :: shared_ptr,std :: auto_ptr。使用这些范例通常不需要自己调用删除。
答案 3 :(得分:2)
你想使用堆,所以我建议你将矢量声明改为指针矢量,就像这样。
vector<Obj *>objList;
为什么呢?因为如果它是Obj的向量,那么你存储的东西实际上是你创建的指针的值Obj的副本。 objList的项目和你创建的obj指针是完全分离和无关的! 所以,当你,
delete obj
objList上的内容在任何方面都完全不受影响
此外,vector<Obj>
(没有星号),将其项目存储为Obj并且它们位于堆栈上,当您的程序超出范围时它们将消失!
答案 4 :(得分:1)
嗯,简单的规则是由new
构建的每个变量都应该由delete
清理。
但是,根据您的目标,您可能不需要自己编写delete
。
在家里,在学习内存管理的血腥细节时,你可能会在编写delete
时编写尽可能多的new
。
然而,专业人士从未在应用代码(*)中使用delete
。 delete
是代码气味。它是存在异常时内存泄漏的最短路径。专业人士使用RAII安全地处理异常,即:智能指针/智能容器。
(*)而不是库代码,即某人有一天写了shared_ptr
课程。