无论你有多少次删除指针,指针都保证保持不变吗?

时间:2010-11-24 16:56:06

标签: c++

以下示例中包含:

AguiWidget::setGlobalFont(segoe);
label->setFont(AguiWidget::getGlobalFont());
label->resizeToText();

delete segoe;
    segoe = 0;
segoe = new AguiFont(std::string("test.ttf"),24);

我原本期望标签崩溃,因为标签的font = globalFont = = segoe。

这总是有效吗?

可以安全地假设,如果我重新创建segoe,使用它的所有小部件都可以,或者使用segoe的小部件的字体会在某些时候受到影响吗?

由于

6 个答案:

答案 0 :(得分:9)

不,当您调用new并将指针指定给其他对象时,指针现在可能指向完全不同的内存地址。旧的内存地址现在无效(因为您在其上调用了delete),并且使用该地址的任何其他代码现在都使用所谓的“悬空指针”。

“悬空指针”是一个指针,它指的是使用有效的内存地址,但由于它指向的对象被解除分配而不再有效。使用悬空指针将导致未定义的行为,并可能导致程序崩溃。

为了使这个程序正常工作,AguiWidget对象应该创建自己的指向对象的内部副本,这样它就不依赖于它不拥有的内存地址。如果事实上AguiWidget对象执行此操作,那么就没有悬空指针问题。但是,AguiWidget对象的内部副本不会因为您更改外部segoe指针而受到影响。相反,您必须再次致电AguiWidget::setGlobalFont

答案 1 :(得分:2)

不,假设这是不安全的。可能会发生一些事情:

  • AguiWidget::setGlobalFont可以将指向的数据复制到新分配中。 (如果没有代码或文档,我无法肯定地说。)如果它确实这样做了,那么你粘贴的代码就可以了。
  • 释放的内存可能不会被新分配覆盖一段时间,因此应用程序可能会继续正常运行,然后在没有明显原因的情况下突然崩溃。
  • 可以为新字体的分配分配与刚刚删除的字体相同的地址。这不太可能,但可能。

答案 2 :(得分:0)

  

可以安全地假设,如果我重新创建segoe,使用它的所有小部件都可以,或者使用segoe的小部件的字体会在某些时候受到影响吗?

这取决于编写您正在使用的小部件工具包的人。如果takeit设计有任何意义,当您将指针传递给方法时,该方法不应在方法终止后对指针进行假设。也就是说,没有人说这样设计

您必须查阅您正在使用的任何小部件工具包的文档。

答案 3 :(得分:0)

如果重新创建segoe,之前使用它的所有小部件都必须指向新位置,因为指针本身(32位或64位值)无疑会发生变化。你现在有一个悬垂的指针,这是一个严重的问题。

答案 4 :(得分:0)

这完全取决于。如果您要发送的课程执行深层复制,那么您可能是安全的。如果没有,那么你将遇到Charles Salvia所说的问题。

答案 5 :(得分:0)

不,没有这样的保证。

但是如果你想重用旧内存并在同一个地方创建一个新对象,那就是一个名为 placement new 的低级功能:

而不是:

delete segoe;
segoe = new AguiFont(...)
你可以:

segoe.~AguiFont(); // destructor called, no memory released -
                   // the pointer now points at allocated, but uninitialized memory
new(segoe) AguiFont(...); // costructor called on the same memory place
                          // the pointer is valid again

但为了安全和正确,我相信以前和新班级必须相同。考虑如果它们具有不同的大小会发生什么,例如(分配的内存仍然是相同的大小!)。