以下示例中包含:
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的小部件的字体会在某些时候受到影响吗?
由于
答案 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
但为了安全和正确,我相信以前和新班级必须相同。考虑如果它们具有不同的大小会发生什么,例如(分配的内存仍然是相同的大小!)。