简单,高效的弱指针,在取消分配目标内存时设置为NULL

时间:2009-12-09 19:15:16

标签: c++ pointers dangling-pointer

是否有一个简单,有效的弱/保护指针?我需要多个指向同一个对象的指针,这些指针在删除对象时都会自动设置为NULL。有一个“主”指针始终用于删除对象,但可能有几个其他指针引用同一个对象。

以下是一些与我的需求不相符的解决方案:

  • QPointer:我没有开发QT应用程序;我不希望在QObject中包含这个libary /派生。
  • boost::weak_ptr访问解除分配的对象时抛出异常。我的情况太贵了:测试弱指针应该是正常的;当弱指针不再有效时,我打算做一些手动清理。 更新:可以测试weak_ptr而不会抛出异常
  • Low-Overhead Weak Pointers:这与我正在寻找的非常接近,除了我不喜欢这样的事实“只要你不分配2 ** sizeof(int,这个方案只能保证工作) )在同一地点的时间。“

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

我希望将调试/统计逻辑与游戏实体分开。游戏实体不应该知道附加了调试/统计对象。虽然我更喜欢弱/保护指针的答案,但我也欢迎不同的方法来处理我的具体任务。我想我可能必须实现跟踪对象生存期的game object manager并使用句柄而不是内存地址的原始指针。

我正在用C ++开发。

2 个答案:

答案 0 :(得分:16)

您可以使用lock()的{​​{1}}成员来测试(然后使用)boost::weak_ptr的值,而无需处理异常。

答案 1 :(得分:10)

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

通常的方法是使用指针指针的详细说明。实体由句柄而不是指针引用。句柄是指向实体的大量指针的索引。当一个实体死掉时,它会将实体表中的指针清空。

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的句柄。因此,我们为每个实体提供一个全局唯一的编号,并将其存储在句柄中。

当然,您可以使用标准向量或地图或字典或其他类型的数据结构作为实体表,但我们的要求通常用于恒定内存,高速缓存一致性和绝对最大性能(因为handle_t :: Get()每帧被调用数千次。