2

这不是问题,只是我想回答的问题。

我正在制作具有粒子的 2D 应用程序。在单击处理程序中,我编写了以下代码:

Particle *tempp = new Particle();
tempp->setPosition(mx, my);
particles.push_back(tempp); // typeof particles = std::list<Particle*>
delete tempp; // <- this line is the problem

当我单击时,将在鼠标位置创建一个粒子。大约一秒钟后,它应该会消失,效果很好。在它消失后,我可以再次单击以创建一个新粒子。

但是,当我在屏幕上仍然有一个粒子时单击时,我的程序会冻结并停止工作。

我的类的Particle构函数和它的父析构函数都是空的。

不调用delete我的程序运行良好,即使一次有多个粒子,甚至每帧多个粒子。我只是想知道是什么导致了这个冻结问题。

4

5 回答 5

5

根据发布的代码,particles容器将包含悬空指针。任何取消引用这些的尝试都是未定义的行为。我假设它们稍后会被使用,否则它们的存储似乎毫无意义。

调用push_back()不会复制指向的对象,而是复制指针的值(动态分配的对象的内存地址)。如果Particle复制成本低,则可复制且不需要多态行为,只需将其存储Particle在容器中即可。否则,建议使用智能指针,例如,在从容器中删除时std::unique_ptr自动销毁。Particle

于 2013-05-09T15:02:57.800 回答
3

当我看到new几行之后delete,我宁愿看到使用的堆栈。除非Particle是巨大的(我怀疑),否则您可以将代码更改为:

Particle tempp;
tempp.setPosition(mx, my);
particles.push_back(tempp); // change particles to std::list<Particle>

快速。你写的代码更少,你就不会崩溃。

于 2013-05-09T15:10:05.420 回答
3

当您将指针推入列表时,您只推入实际指针的副本,而不复制它所指向的内容。这意味着在push_back您有两个指向同一内存的指针之后。

如果您随后释放该内存,那么您有一个指向释放内存的指针,并且该指针现在无效。

于 2013-05-09T15:03:19.850 回答
2

我相信解决方案在于您的第三行代码。请注意,particles 是指向 Particles 的指针向量?那么,在第 3 行中,您创建了指针的副本并将其插入到列表中。在下一行,您释放该指针指向的内存。该列表不存储您的粒子 - 它仅存储粒子的内存地址因此,当您删除粒子时,您告诉编译器重新使用包含您的有效数据的内存。

因此,虽然评论第 4 行会使问题消失,但它实际上并没有在那里崩溃——没有理由让它崩溃。可能的情况是它在尝试对曾经属于你的内存做某事时崩溃,但在第 3 行被释放。

您可以使列表存储实际的粒子作为修复。

于 2013-05-09T15:08:53.263 回答
2

您将 apointer放入容器中,然后将其删除,这是一个问题。push_back将复制的值pointer不是 the 的内容,pointer所以当您调用时deletepointer容器中的 the 不再有效。所以现在你有一个悬空指针,当你取消引用它时,这将是未定义的行为,但很可能是崩溃。

于 2013-05-09T15:04:00.650 回答