unordered_map
有五个参数,分别是键类型(Key Type
)、值类型(Value Type
)、哈希函数(Hash Function
)、相等键函数(Equal Key Function
)和空间分配器(Allocator
)。
当我们创建一个unordered_map
时,我们需要提供五个参数。
键类型(Key Type
):这是用来定义键的数据类型。键可以是任何数据类型,比如整数、浮点数、字符串等。
值类型(Value Type
):这是用来定义值的数据类型。值可以是任何数据类型,与键的数据类型可以相同,也可以不同。
哈希函数(Hash Function
):这是用来计算键的哈希值的函数。哈希函数将键映射为一个整数值,这个值用来确定键在unordered_map
中的位置。哈希函数需要满足一些要求,比如相同的键应该有相同的哈希值。
相等键函数(Equal Key Function
):这是用来判断两个键是否相等的函数。当两个键的哈希值相同时,unordered_map
需要使用相等键函数来判断它们是否真正相等。相等键函数需要返回一个bool
值,如果两个键相等则返回true
,否则返回false
。
空间分配器(Allocator
):这是用来分配和释放内存的函数对象。unordered_map
使用空间分配器来管理内存,包括为键值对分配内存、释放内存以及重新分配内存等操作。默认情况下,unordered_map
使用标准分配器来实现内存管理,但也可以使用自定义的空间分配器。
std::allocator
是C++标准库提供的默认的空间分配器。它使用了new和delete操作符来进行内存的分配和释放。
当我们使用std::allocator来分配内存时,它会调用new运算符来分配一块足够大小的原始内存块。std::allocator的allocate函数接收一个size_t
类型的参数,表示需要分配的内存块的大小。allocate函数会计算出需要分配的内存块的大小,并调用new运算符来分配内存。然后,allocate函数会返回分配的内存块的指针。
当我们使用std::allocator来释放内存时,它会调用delete运算符来释放先前分配的内存块。std::allocator的deallocate函数接收两个参数,第一个参数是要释放的内存块的指针,第二个参数是内存块的大小。deallocate函数会调用delete运算符来释放内存。std::allocator的分配和释放过程与new和delete运算符的行为一致,可以通过重载new和delete运算符来实现自定义的内存分配和释放逻辑。默认情况下,std::allocator的行为与全局的new和delete运算符一致,可以直接使用。
自定义的空间分配器是指用户可以根据自己的需求定义的分配和释放内存的函数对象。通常情况下,unordered_map使用标准分配器来实现内存管理,即使用std::allocator来分配和释放内存。但是,在特定的情况下,用户可能希望使用不同的内存分配策略或者使用自己实现的内存管理机制。
使用自定义的空间分配器可以实现以下功能:
- 改善性能:用户可以针对自己的应用场景选择更适合的分配策略,以提高unordered_map的性能。
- 约束资源使用:用户可以通过自定义空间分配器来限制资源的使用,以防止内存泄漏或过度使用内存。
- 支持特殊需求:在某些特殊的场景下,用户可能需要使用特定的内存分配策略或者与其他库兼容的内存管理机制,此时可以通过自定义空间分配器来满足这些需求。
自定义空间分配器需要实现以下两个成员函数:
- allocate函数:用于分配内存。该函数接受一个size_t类型的参数,表示需要分配的内存块的大小,返回一个指向分配的内存块的指针。
- deallocate函数:用于释放内存。该函数接受两个参数,第一个参数是要释放的内存块的指针,第二个参数是内存块的大小。
用户可以通过定义自己的空间分配器类,并重载这两个成员函数来实现自定义的空间分配器。在创建unordered_map对象时,可以将自定义的空间分配器作为参数传递给unordered_map的模板参数,以使用自定义的空间分配器。
提供这五个参数可以让我们更好地自定义unordered_map的行为,比如选择合适的键和值类型、调整哈希函数以提高性能、使用自定义的相等键函数来处理复杂的键比较逻辑等。
构建自定义的哈希表:除了键值之外,要设置两个函数,一个是计算键值的hash函数,另一个是比较键值是否相等的函数,这里对应的分别是PersonHash
和PersonEqual
两个函数。
#include <iostream>
#include <unordered_map>
class person{
public:
enum class name
{
Li =1,
Wu =2,
};
name name_=name::Li;
};
class ani{
public:
enum class sex{
boy = 1,
girl = 2,
};
sex pet = sex::boy;
};
struct PersonHash {
std::size_t operator()(const person& p) const {
// 使用哈希函数来计算person对象的哈希值
return static_cast<std::size_t>(p.name_);
}
};
struct PersonEqual {
bool operator()(const person& p1, const person& p2) const {
// 使用比较函数来比较person对象的值
return p1.name_ == p2.name_;
}
};
int main() {
person a;
a.name_=person::name::Li;
ani b;
b.pet=ani::sex::boy;
person::name n = person::name::Li;
std::unordered_map<person, ani,PersonHash,PersonEqual> umap;
umap.insert(std::make_pair(a,b));
// std::cout<<umap[n]<<std::endl;
std::cout<<static_cast<size_t>(umap.at(a).pet)<<std::endl;
return 0;
}