两个std::hash<type>实例是否等价?C++哈希函数标准合规性疑问
C++哈希函数断言的正确性解析
你提出的问题核心是:这段代码里的断言是否应该成立?
my_type k; assert(my_hasher{}(k) == my_hasher{}(k));
cppreference明确说断言应当成立,但C++标准[hash.requirements](16.5.3.4)只提到“特定哈希实例对同一参数的返回值在程序运行期间仅依赖于参数k”,看起来好像允许不同实例返回不同值。其实是你漏看了标准对哈希函数的隐含要求,cppreference的表述并没有错误。
标准的完整要求:哈希函数必须是正则类型
C++标准对哈希函数的要求不止单个实例的稳定性:
- 哈希函数属于函数对象类型,必须满足*正则性(Regular)*的要求。正则类型的核心特征之一是:所有默认构造的实例都是等价的——也就是说,用默认构造的不同实例执行相同操作,必须得到相同结果。
- 换个直白的说法:符合标准的哈希函数要么是无状态的,要么其状态不会影响哈希计算逻辑。如果一个哈希函数默认构造的实例会因为自身状态不同而返回不同结果,那它根本不满足标准对哈希函数的定义。
为什么标准要这么要求
标准库的无序容器(比如unordered_map、unordered_set)依赖哈希函数的一致性:不同容器实例各自持有自己的哈希函数对象,如果这些对象对同一键返回不同哈希值,容器的行为会完全混乱——比如同一个键在不同容器里被分到不同桶,甚至在同一个容器的不同操作中也会出问题。所以标准通过正则性要求,间接强制了默认构造的哈希实例必须等价。
特殊情况:有状态哈希函数
如果my_hasher是自定义的有状态哈希函数,且状态会影响计算结果,那它本身就不符合C++标准的哈希函数要求。这种情况下你的断言可能不成立,但这样的哈希函数也不能被标准库无序容器正确使用。
内容的提问来源于stack exchange,提问作者Igor R.
相关产品推荐
相关产品推荐

