为啥c ++ std::hash会创建一个仿函数结构并且可以在不每次创建结构的情况下调用它

Posted

技术标签:

【中文标题】为啥c ++ std::hash会创建一个仿函数结构并且可以在不每次创建结构的情况下调用它【英文标题】:Why does c++ std::hash create a functor struct and can it be called without creating a struct each time为什么c ++ std::hash会创建一个仿函数结构并且可以在不每次创建结构的情况下调用它 【发布时间】:2020-06-01 13:37:17 【问题描述】:

我正在编写一个程序,该程序需要非常快速地以线程安全的方式执行大量哈希。无论出于何种原因,c++ 的 std::hash 似乎都需要在每次你想要散列一个值时构造一个仿函数

std::hash<std::string>(data);

我非常担心每次我想要散列一个值时分配整个结构的开销,但我不明白在这种情况下甚至需要仿函数的实际原因。

创建一个哈希结构然后多次调用其operator() 是否安全/正确?

std::hash<std::string> strHash;
strHash(data1);
strHash(data2);

重用一个哈希结构会是线程安全的吗?如果没有,我将如何使它更线程安全?

【问题讨论】:

在大多数情况下,std::hash&lt;std::string&gt; 只是一个带有成员 operator() 的空结构,因此只需进行基本优化,std::hash&lt;std::string&gt; 就没有开销。 【参考方案1】:

但我不明白函子在这种情况下甚至是必要的实际原因。

std::hash 是函子而不是函数有一个很好的理由,那就是它可以有状态。 C++ 标准允许使用加盐哈希,因此同一程序的每次执行都可以为相同的原始值创建不同的哈希值。

创建一个哈希结构然后多次调用它的 operator() 是否安全/正确?

std::hash<std::string> strHash;
strHash(data1);
strHash(data2);

是的,该代码是安全的。每次你想要散列一些东西时,你不需要构造一个hash。可以创建单个哈希对象并将其用于您需要的所有哈希(在单线程环境中)。

重用一个哈希结构会是线程安全的吗?如果没有,我将如何使它更线程安全?

取决于用途,但很可能不是。 std::hash 没有线程安全保证,因此您需要使用互斥锁或其他一些同步技术来保护对它的访问。或者您可以每个线程只使用一个哈希对象,因为它们需要为相同的输入提供相同的输出。这会给您带来一点额外的空间开销,但现在您没有任何可能会很昂贵的同步开销。

【讨论】:

以上是关于为啥c ++ std::hash会创建一个仿函数结构并且可以在不每次创建结构的情况下调用它的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 SpriteKit update() 函数会创建多个 NSTimers?

为啥我的更新函数会创建一个全新的力导向图?

如果键不存在,为啥 std::map operator[] 会创建一个对象?

为啥 Visual Studio 转换向导 2010 会创建海量的 SDF 数据库文件?

为啥 C++11 不能将不可复制的仿函数移动到 std::function?

为啥 React.createElement() 会创建一个对象?