Oh!Coder

Coding Life

第十一章 其它

| Comments

声明:此文章翻译自Box2D v2.2.0用户手册,仅供学习参考。

11.1 隐式销毁(Implicit Destruction)

Box2D没有使用引用计数。如果你销毁了一个物体那就真的消失了。通过指针来销毁物体,此指针将会变成未定义状态。换句话说,程序有可能面临崩溃。为了帮助定位这些问题,为了更好的调试这些指针,内存管理将这种情况下的指针填充了FDFDFDFD信息。在一些场景中,这可以更简单的帮助你发现问题。

如果你销毁一个Box2D实体,需要确保所有对象移除了此实体的引用。对于单个引用实体来说这很简单。如果你有多个引用,你或许会考虑封装一个handle class来处理这些原始指针。

通常使用Box2D你会创建许多物体,形状,还有连接器。Box2D有些可以自动完成这些实体的管理。如果你销毁一个物体,那么就会自动销毁所有与之关联的形状和连接器。这就称为隐式销毁(implicit destruction)。

当你销毁一个物体,所有附加到在它身上的形状,连接器以及接触都会被销毁。这叫做隐式销毁。与其中任何一个连接器以及(或者)接触相关联的物体都被唤醒。这么处理很方便。即使这样,你必须意识到一个关键的问题:

警告
当一个物体销毁时,所有附加在此物体上的定制器以及连接器都会被自动销毁。必须废弃这些形状和连接器的任何指针。否则,你的程序如果再次试图访问或销毁这些形状或者连接器的指针,那么将会死的很难看。

为了更好的帮助你废弃连接器的指针,Box2D提供了一个名为b2DestructionListener的监听器类(listener class)来为你实现并为世界中的物体提供这些功能。那么当一个连接器被隐式销毁之后,世界对象会发给你发送一条通知。

注意当连接器或者定制器被明确销毁之后是没有通知的。这种情况下所有权是明确的,你可以当场执行需要清理的代码。如果你喜欢,你可以调用你自己实现的b2DestructionListener来保持代码统一。

隐式销毁在很多情况下带来了极大的便利。当然它也可以让你的程序四分五裂。你可以在程序的某个地方存储形状或者连接器的指针。当一个相关的物体被销毁后这些指针将会变成野指针。当你认为连接器经常被与物体不相关的部分代码进行创建的时候,情况会变的更糟糕。比如说,testbed中为屏幕上交互的物体创建的一个b2MouseJoint(鼠标连接器)。

当隐士销毁发生时,Box2D为程序提供了一个回调通知机制。这就给了一个让你废除野指针的机会。稍后会对回调机制进行描述。

你可以实现b2DestructionListener来让b2World通知你由于一个物体被销毁而引起相关的形状和连接器被隐式销毁的消息。这可以帮助你的代码访问野指针。

1
2
3
4
5
6
7
class MyDestructionListener : public b2DestructionListener
{
    void SayGoodbye(b2Joint*  joint)
    {
        //remove all references to joint.
    }
}

之后你可以使用世界对象注册一个销毁监听器的实例。在世界初始化的时候你应该这样做:

1
myWorld->SetListener(myDestructionListener);

Comments