作者试图帮助您避免重复散列字符串时发生的意外性能问题。由于散列字符串的成本很高,因此您可能需要执行一次并将其缓存在某个地方。如果它们具有隐式构造函数,您可以在不知情或不打算这样做的情况下重复散列同一字符串。
所以图书馆提供implicit字符串文字的构造,可以在编译时通过以下方式计算constexpr
but explicit建设为const char*
一般来说,因为这些通常不能在编译时完成,并且您希望避免重复或意外地这样做。
考虑:
void consume( hashed_string );
int main()
{
const char* const s = "abc";
const auto hs1 = hashed_string{"my.png"}; // Ok - explicit, compile-time hashing
const auto hs2 = hashed_string{s}; // Ok - explicit, runtime hashing
consume( hs1 ); // Ok - cached value - no hashing required
consume( hs2 ); // Ok - cached value - no hashing required
consume( "my.png" ); // Ok - implicit, compile-time hashing
consume( s ); // Error! Implicit, runtime hashing disallowed!
// Potential hidden inefficiency, so library disallows it.
}
If I remove the last line, you can see how the compiler applies the implicit conversions for you at :
consume(hashed_string(hs1));
consume(hashed_string(hs2));
consume(hashed_string("my.png"));
但它拒绝为该线路这样做consume(s)
因为隐式/显式构造函数。
但请注意,这种保护用户的尝试并非万无一失。如果将字符串声明为数组而不是指针,则可能会意外地重新散列:
const char s[100] = "abc";
consume( s ); // Compiles BUT it's doing implicit, runtime hashing. Doh.
// Decay 's' back to a pointer, and the library's guardrails return
const auto consume_decayed = []( const char* str ) { consume( str ); }
consume_decayed( s ); // Error! Implicit, runtime hashing disallowed!
This case is less common, and such arrays typically get decayed into pointers as they are passed to other functions, which would then behave as above. The library could conceivably enforce compile-time hashing for string literals with if constexpr
and the like and forbid it for non-literal arrays like s
above. (There's your pull request to give back to the library!) [See comments.]
回答你的最后一个问题:这样做的原因是为了让基于哈希的容器具有更快的性能,例如std::unordered_map
。它通过计算一次哈希值并将其缓存在内部,最大限度地减少了必须执行的哈希值数量。hashed_string
。现在,映射中的键查找只需比较键和查找字符串的预先计算的哈希值。