📜  C++ STL中的std :: hash类(1)

📅  最后修改于: 2023-12-03 15:29:50.982000             🧑  作者: Mango

C++ STL中的std::hash类

在C++ STL中,std::hash是一个用于计算哈希值的模板类,可以用于STL容器中的键值对的查找和存储等操作。在本文中,我们将介绍std::hash的定义、使用方法和一些注意事项。

std::hash的定义

std::hash是一个模板类,定义在命名空间std中,其声明如下:

namespace std {
  template <class T>
  struct hash;
}

std::hash的模板参数T可以是任意类型,但必须满足以下要求:

  • T必须是可用于哈希的类型;
  • T必须是可复制的类型;
  • T必须提供operator==

如果T是一个结构体或类类型,它还必须重载operator=

std::hash的使用方法

使用std::hash计算哈希值通常需要两步操作:

  1. 定义一个哈希对象;
  2. 调用哈希对象的operator()计算哈希值。

例如,以下代码定义了一个std::hash<int>类型的哈希对象,并使用它计算整数1的哈希值:

#include <iostream>
#include <functional>

int main() {
  std::hash<int> hasher;
  std::cout << hasher(1) << std::endl;
  return 0;
}

输出结果为:

1

std::hashoperator()函数可以接收多个参数,其参数列表取决于模板参数T。例如,对于T为std::string的情况,operator()会接收一个const std::string&类型的参数。

以下代码定义了一个std::hash<std::string>类型的哈希对象,并使用它计算字符串"hello"的哈希值:

#include <iostream>
#include <string>
#include <functional>

int main() {
  std::hash<std::string> hasher;
  std::cout << hasher("hello") << std::endl;
  return 0;
}

输出结果为:

7372389891653670756
注意事项

在使用std::hash时需要注意以下几点:

  • 对于相同的输入,std::hash保证返回相同的哈希值;
  • 哈希值的分布应该尽可能的均匀,以便于哈希表等数据结构的高效运作;
  • 对于一些特定类型(如指针),std::hash的默认实现可能不够好,需要自定义哈希函数。

使用自定义哈希函数的示例代码如下:

#include <iostream>
#include <string>
#include <unordered_map>

struct MyStruct {
  std::string name;
  int age;
  bool operator==(const MyStruct& other) const {
    return name == other.name && age == other.age;
  }
};

namespace std {
  template <>
  struct hash<MyStruct> {
    size_t operator()(const MyStruct& obj) const {
      return hash<std::string>()(obj.name) ^ hash<int>()(obj.age);
    }
  };
}

int main() {
  std::unordered_map<MyStruct, int> m{{{"Alice", 18}, 1}, {{"Bob", 20}, 2}};
  std::cout << m[{"Alice", 18}] << std::endl;
  return 0;
}

输出结果为:

1

在上面的例子中,我们为自定义结构体MyStruct定义了一个哈希函数,并使用std::unordered_map进行了测试。需要注意的是,自定义哈希函数的定义方式与一般的模板函数不同,需要将其定义在命名空间std中的模板特化中。此外,在自定义哈希函数时,通常可以将不同的哈希函数结果取异或运算,以获得更好的哈希值分布。