用整数散列替换字符串名称的一些好方法是什么

What are some good methods to replace string names with integer hashes

本文关键字:是什么 方法 整数 替换 字符串      更新时间:2023-10-16

通常,数据驱动设计中的实体和组件或游戏代码的其他部分都会有名称,如果你想知道你正在处理的是哪个对象,就会对其进行检查。

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位值,而不是一个实际的字符串,那么查找实体的速度会快得多。

计算字符串名称的散列是一种可能的选择。我还没有真正尝试过,但有了32位的范围和良好的哈希函数,碰撞的风险应该是最小的。

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

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

Jason Gregory在他的书中写道:

在Naughty Dog,我们使用了CRC-32算法的变体来散列字符串,在《Uncharted:Drake’s Fortune》的两年多开发过程中,我们没有遇到任何冲突。

所以你可能想调查一下。

关于你提到的构建步骤,他也谈到了。它们基本上封装了需要散列的字符串,比如:

_ID("string literal")

并在构建时使用外部工具对所有出现的情况进行散列。这样可以避免任何运行时成本。

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

我会说使用枚举!

但是,如果你已经有很多代码已经使用了字符串,那么,要么保持这种方式(无论如何,在PC上都很简单,通常足够快),要么使用某种CRC或MD5将其散列为整数。

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

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

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

注意事项:

  • 此策略使从句柄中取回字符串的操作在恒定的时间内运行(这只是一个数组的尊重)
  • 句柄标识符是先到先得的,但如果序列化字符串而不是值,那就无关紧要了
  • 键和值的运算符[]重载相当简单(注册新字符串或取回字符串),但用用户定义的类包装句柄(包装整数)可以增加许多急需的类型安全性,并且如果希望键和值是相同的类型,也可以避免歧义(重载[]不会编译等)
  • 您必须将字符串存储在RAM中,这可能是一个问题