用整数哈希替换字符串名称有什么好方法

时间:2012-01-04 16:39:39

标签: c++ string

通常,数据驱动设计中的实体和组件或游戏代码的其他部分将具有检查的名称,如果您想要找出您正在处理的对象。

void Player::Interact(Entity *myEntity)
{
    if(myEntity->isNearEnough(this) && myEntity->GetFamilyName() == "guard")
    {
       static_cast<Guard*>(myEntity)->Say("No mention of arrows and knees here");
    }
}

如果你忽略了这可能是过早优化的可能性,很明显,如果他们的“名称”是一个简单的32位值而不是实际的字符串,查找实体会快得多。

计算字符串名称中的哈希是一种可能的选择。我实际上没有尝试过,但是在32bit的范围和良好的散列函数下,碰撞的风险应该是最小的。

问题是:显然我们需要某种方法将代码内(或某种外部文件中)字符串名称转换为那些整数,因为处理这些命名对象的人仍然希望引用该对象作为“守卫”而不是“0x2315f21a”。

假设我们正在使用C ++并希望替换代码中出现的所有字符串,这甚至可以通过语言内置功能实现,还是我们必须构建一个外部工具来手动浏览所有文件并交换值?

4 个答案:

答案 0 :(得分:10)

Jason Gregory在his book上写了这个:

  

在Naughty Dog,我们使用CRC-32算法的变体来对我们的字符串进行哈希处理,并且在Uncharted:Drake's Fortune的两年多的开发中我们没有遇到过一次冲突。

所以你可能想看一下。

关于你提到的构建步骤,他也谈到了它。它们基本上封装了需要在以下内容中进行哈希处理的字符串:

_ID("string literal")

在构建时使用外部工具来散列所有出现的内容。这样可以避免任何运行时成本。

答案 1 :(得分:1)

这就是枚举的用途。我不敢决定哪个资源最适合这个主题,但有很多选择:https://www.google.com/search?q=c%2B%2B+enum

答案 2 :(得分:0)

我会说与enums一起去!

但是如果你已经有很多代码已经使用了字符串,那么,或者只是保持这种方式(简单而且通常在PC上足够快)或使用某种CRC或{{ 3}}成一个整数。

答案 3 :(得分:0)

这基本上是通过在哈希映射之上添加间接来解决的。

假设您要将字符串转换为整数:

  • 编写一个包装数组和一个hashmap的类。我将这些类称为字典。
  • 数组包含字符串。
  • 哈希映射的关键是字符串(原始指针安全工作的共享指针或稳定数组)
  • 哈希映射的值是字符串所在数组的索引,也是它返回调用代码的不透明句柄。
  • 向系统添加新字符串时,会搜索已存在于散列映射中的字符串,如果存在则返回句柄。
  • 如果句柄不存在,请将字符串添加到数组中,索引是句柄。
  • 在地图中设置字符串和句柄,然后返回句柄。

注释/注意事项:

  • 这个策略使得从句柄运行中获取字符串的时间是恒定的(它只是一个数组deference)。
  • 句柄标识符是先到先得的,但是如果序列化字符串而不是值,则无关紧要。
  • 对于键和值的Operator []重载都非常简单(注册新字符串,或者返回字符串),但是使用用户定义的类(包装整数)包装句柄会增加很多需要类型安全,如果你想要键和值是相同的类型(重载[]不会编译等),也避免歧义
  • 您必须将字符串存储在RAM中,这可能是个问题。