2009-12-09 16 views
8

是否存在简单,高效的弱/保护指针?我需要指向同一个对象的多个指针,当对象被删除时它们全部自动设置为NULL。有一个总是用来删除对象的“主”指针,但可以有几个指向同一对象的其他指针。简单高效的弱指针在释放目标内存时设置为NULL

这里有一些解决方案,不完全匹配我的需求:

  • QPointer:我不是开发一个应用程序QT;我不希望包含这个库文件/派生自QObject。
  • boost::weak_ptr访问解除​​分配的对象时引发异常。我的情况太昂贵了:测试弱指针应该是正常的;我计划在弱指针不再有效时进行一些手动清理。更新:weak_ptr的,而不抛出异常
  • Low-Overhead Weak Pointers进行测试:这是非常接近我所期待的,但我不喜欢的事实,“该方案只保证,只要你不上班t在同一位置分配2 ** sizeof(int)次。“

为什么需要这些弱/把守指针: 我有一个游戏对象的列表中的游戏。某些对象依赖于其他对象,例如与游戏实体关联的调试/统计对象。调试/状态对象显示有关游戏实体的有用信息,但只有在游戏实体存在时才有意义。所以如果游戏实体被删除,debug/stats对象应该实现这一点并删除它自己。 (另一个想法是跟踪导弹:不是删除它自己,它可能会搜索新的目标。)

我希望将调试/统计逻辑与游戏实体分开。游戏实体不应该知道调试/统计对象被附加到它。虽然我更愿意回答弱/保守的指针,但我也欢迎不同的方式来处理我的具体任务。我想我可能不得不实现跟踪对象生命周期的game object manager,并使用句柄代替指向内存地址的原始指针。

我正在用C++进行开发。

+0

一个普遍的问题是,“Qt是开发游戏的正确选择吗?” – 2009-12-09 19:47:41

+3

Boost的弱指针允许您测试它是否有效。如果直接尝试解引用它,它只会引发异常 - 类似于如果尝试解引用空指针会发生的情况。 – jalf 2009-12-09 19:48:07

+0

C++ 11有['std :: weak_ptr'](http://en.cppreference.com/w/cpp/memory/weak_ptr)。看起来类似于Boost的那个。 – Palec 2017-08-03 16:25:33

回答

16

您可以使用boost::weak_ptrlock()成员来测试(然后使用)weak_ptr的值而不处理异常。

10

这是游戏开发中常见的事情。通常使用对象句柄系统而不是Boost弱指针,因为我们需要底层查找表作为常量内存,因为有时我们需要一些额外的信息或保证Boost没有得到。

通常的做法是对指向指针的指针进行细化。一个实体被句柄而不是指针所引用。句柄是指向实体的大量指针的索引。当一个实体死亡时,它将其实体表中的指针NULL。

struct handle_t 
{ 
    uint32 serialnumber; // this is a GUID for each entity; it increases 
         // monotonically over the life of the process 
    uint entityindex; 
    inline Entity *Get(); 
} 

struct entityinfo_t 
{ 
    Entity *pEntity; // an entity's destructor NULLs this out on deletion 
    uint32 serialnumber; 
} 

entityinfo_t g_EntityTable[MAX_ENTITIES]; 

Entity *handle_t::Get() 
{ 
    entityinfo_t &info = g_EntityTable[entityIndex]; 
    if (serialnumber == info.serialnumber) 
    { 
    return info.pEntity; 
    } 
    else 
    { 
     return NULL; 
    } 
} 

的序列号是必要的,因为数组大小不变的 - 最终,你将需要回收实体表项,并有,你可以存储一个句柄,也就是说,指数#743的可能性,足够长的时间以便删除对象并将单元#743重新用于其他内容。如果你只是有一个指向指针列表的指针,你最终会得到一个指向完全不同对象的句柄,而不是NULL。所以,我们给每个实体一个全球唯一的编号并将其存储在句柄中。

当然,您可以使用std向量或映射或字典或某种其他类型的实体表的数据结构,但我们的要求通常用于恒定内存,缓存一致性和绝对最大性能(自handle_t :: Get()每帧调用数千次)。