5

使用 GCC 4.4(通常是 Android 和 IOS 可用的最大值)有一种方法可以对字符串进行编译时散列。

我们有一个将字符串键映射到资源的资源管理器。虽然查找速度很快,但散列和字符串创建速度很慢。就像是:

 ResourcesManager::get<Texture>("someKey");

花费大量时间分配字符串“someKey”,然后对其进行哈希处理。

我想知道是否有一个技巧可以在编译时使用它来散列它。

4

3 回答 3

7

您必须实现正确的散列算法,但这可以使用 C++11 的 constexpr 函数来工作:

#include <iostream>

// Dummy hashing algorithm. Adds the value of every char in the cstring.
constexpr unsigned compile_time_hash(const char* str) {
    // Modify as you wish
    return (*str == 0) ? 0 : (*str + compile_time_hash(str + 1));
}   

int main() {
    unsigned some_hash = compile_time_hash("hallou");
    std::cout << some_hash << std::endl;
}

然后你可能有一个重载,ResourcesManager::get它的结果是compile_time_hash(在这种情况下是无符号的)。

这显然取决于您应用的散列算法。使用 constexpr 实现类似 SHA* 的东西会非常痛苦。

请注意,您需要 GCC >= 4.6 或 clang >= 3.1 才能使用 constexpr。

于 2012-07-09T18:45:48.887 回答
2

为了进行编译时散列,所有键都需要是编译时常量。

使用编译时常量进行索引的常用方法不是使用字符串,而是使用枚举类型。这具有根本不需要散列的优点,因为常量是连续的并且可以直接索引数组。

enum KeyType
{
    someKey,
    someOtherKey
};

ResourcesManager::get<Texture>(someKey);

如果需要将键作为字符串获取,只需保留一个可以由枚举常量索引的字符串表。

static char * keyNames = 
{
    "someKey",
    "someOtherKey"
};
于 2012-07-09T18:58:49.327 回答
0

你总是可以编译一个程序来散列你的字符串并输出合适的源代码......

我自己,我实际上并没有对字符串进行散列,我只是枚举项目并输出带有枚举的头文件。很好很容易,没有冲突等。

于 2012-07-09T18:48:50.690 回答