用整数散列替换字符串名称的一些好方法是什么
What are some good methods to replace string names with integer hashes
通常,数据驱动设计中的实体和组件或游戏代码的其他部分都会有名称,如果你想知道你正在处理的是哪个对象,就会对其进行检查。
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")
并在构建时使用外部工具对所有出现的情况进行散列。这样可以避免任何运行时成本。
我会说使用枚举!
但是,如果你已经有很多代码已经使用了字符串,那么,要么保持这种方式(无论如何,在PC上都很简单,通常足够快),要么使用某种CRC或MD5将其散列为整数。
这基本上是通过在哈希映射上添加间接来解决的。
假设要将字符串转换为整数:
- 编写一个类同时包装一个数组和一个hashmap。我把这些课称为字典
- 数组包含字符串
- 哈希映射的键是字符串(共享指针或稳定数组,其中原始指针也可以安全工作)
- 哈希映射的值是字符串所在数组的索引,也是它返回给调用代码的不透明句柄
- 当向系统添加新字符串时,会搜索hashmap中已经存在的字符串,如果存在,则返回句柄
- 如果句柄不存在,请将字符串添加到数组中,索引就是句柄
- 在映射中设置字符串和句柄,然后返回句柄
注意事项:
- 此策略使从句柄中取回字符串的操作在恒定的时间内运行(这只是一个数组的尊重)
- 句柄标识符是先到先得的,但如果序列化字符串而不是值,那就无关紧要了
- 键和值的运算符[]重载相当简单(注册新字符串或取回字符串),但用用户定义的类包装句柄(包装整数)可以增加许多急需的类型安全性,并且如果希望键和值是相同的类型,也可以避免歧义(重载[]不会编译等)
- 您必须将字符串存储在RAM中,这可能是一个问题
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 通过JNI传递数据数组的最快方法是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 在另一个类视图中添加最多2个图表的正确方法是什么
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 在C++中包含原型文件的正确方法是什么?
- 在 OpenCV C++ 中估计基本矩阵之前对相应点进行归一化的正确方法是什么?
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 在OSX上使用CMake将Adobe的XMP工具包构建为共享库的最简单方法是什么?
- 将一系列整数放入类的最佳方法是什么?
- 从长整整转换为uint64_t的推荐方法是什么?
- C++:使用方法调用析构函数的顺序是什么?
- 将此布尔值传递给此函数的最有效方法是什么?