我一直试图解决这个问题,但不能完全理解它。
假设我在头文件中声明了一个对象,例如:
#ifndef SOMECLASS_H
#define SOMECLASS_H
#include "otherclass.h"
class SomeClass
{
public:
SomeClass();
OtherClass *obj;
};
#endif // SOMECLASS_H
我可以在代码中执行以下操作吗?
obj = new OtherClass();
//Do something
delete obj;
obj = new OtherClass();
//Do something else
delete obj;
或者我是否必须创建新的obj
?
我无法想到我可能需要这样做的原因但是我想知道它是否会起作用以及它是否是一个好主意(我知道最好创建对象堆栈一般但为了论证,让我们说在这种情况下它不是一个选项)。
答案 0 :(得分:6)
我认为你需要调整你的心理模型。让我们看一个更简单的案例,我们没有SomeClass
类:
int main() {
OtherClass *obj = new OtherClass();
delete obj;
obj = new OtherClass();
delete obj;
}
第一行是此函数是声明。该声明引入了一个名为obj
的对象,其类型为OtherClass*
。这里重要的是obj
只是一个指针。它不是OtherClass
对象。它只保留一个地址。所以当你谈论对象obj
时,你正在谈论指针。
此声明的初始化为= new OtherClass()
。 表达式 new OtherClass()
也引入了一个对象,但这次它没有被命名。该对象具有类型OtherClass
。表达式返回指向您用于初始化OtherClass
的{{1}}对象的指针。所以现在obj
指针对象指向obj
对象。
此内存模型如下所示:
OtherClass
现在,您可以在其生命周期内使用对象。 obj
+-------------+ +------------+
| OtherClass* |----->| OtherClass |
+-------------+ +------------+
的生命周期是我们声明它的函数的范围。在函数结束时,obj
超出范围并被销毁。也就是说,指针被销毁。 obj
对象的生命周期持续到我们在指向它的指针上使用OtherClass
为止。 delete
只会破坏delete
对象,而不会破坏指针。所以在第一个OtherClass
之后,我们有了这个:
delete
指针仍然存在。它甚至还指向同一个地方,但那里的物体现在已经消失了。
此时,我们无法尝试使用 obj
+-------------+
| OtherClass* |----->
+-------------+
对象,因为它不再存在。但是,我们当然可以重用指针对象OtherClass
。当我们执行obj
(这是一个表达式,而不是声明)时,我们创建一个新的obj = new OtherClass()
对象并设置OtherClass
以指向它。我们回到这种情况:
obj
然后我们再次 obj
+-------------+ +------------+
| OtherClass* |----->| OtherClass |
+-------------+ +------------+
。
此示例与您的示例之间的唯一区别是delete
是obj
的成员。 SomeClass
类型的每个对象都将在其中包含一个名为SomeClass
的{{1}}指针。 OtherClass*
的生命周期现在是obj
对象的生命周期。只要该对象仍然存在,您就可以以任何您喜欢的方式使用obj
。当然,如果你SomeClass
它指向的对象,你就不能使用那个对象。
答案 1 :(得分:3)
您的代码没问题。
如果您愿意,可以随时重复使用指针。
obj = new OtherClass();
delete obj;
obj = new OtherClass();
请记住,当您调用delete时,请调用OtherClass析构函数。
这是一种很好的做法,但不是必需的,删除后将指针置于零。
obj = 0;
这是因为,如果要删除指针后要测试,例如
if(!obj) {
...
}
据说!obj == true。
答案 2 :(得分:2)
您的代码很好,但在C ++ 11中考虑使用unique_ptr以避免必须手动调用“delete”。例如:
std::unique_ptr<OtherClass> obj(new OtherClass());
//Do something
obj.reset(new OtherClass()); //this deletes the previous object
//Do something else. The object will be deleted when obj goes out of scope.
另外,您可能需要考虑将标题更改为“删除指向的对象后可以重新分配指针吗?”
答案 3 :(得分:0)
是的,它会起作用。当你做第二次
obj = new OtherClass();
obj指向已删除的内存,但您将其设置为新值。它没有任何问题。
答案 4 :(得分:0)
你的代码很好。
根据OtherClass
的工作原理,您可以考虑:
obj = new OtherClass();
//Do something
// then do something else
delete obj;
但这并不总是可行的。如果这不适用于您的情况,那么您目前正在做的就是确定。
我在第二个obj = NULL;
之后做delete
。以防万一我需要在其他地方测试这个指针的值,以确定它是否在使用中。
答案 5 :(得分:0)
总结:您不能使用已删除的类的实例,但您可以重用用于存储实例地址的变量指针。
也就是说,您不能执行以下操作(来自您的代码示例):
obj = new OtherClass();
delete obj;
obj->objMethod(); // dereferencing a now invalid pointer => dangerous.
但你可以做你在问题中所写的内容:
obj = new OtherClass();
//Do something
delete obj;
obj = new OtherClass();
//Do something else
delete obj;
实际上,最后一个代码示例与以下代码一样有效(使用简单的int
):
int i = 42;
// Do something
i = 15;
// Do something