C++ STL:unordered_map 自定义键值类型

相关内容: C++ STL: map自定义键值类型

本文目录

1. unordered_map的定义

下面是unordered_map的官方定义。

template<class Key,
    class Ty,
    class Hash = std::hash<Key>,
    class Pred = std::equal_to<Key>,
    class Alloc = std::allocator<std::pair<const Key, Ty> > >
    class unordered_map;
    > class unordered_map
  • 第1个参数,存储key值。

  • 第2个参数,存储mapped value。

  • 第3个参数,为哈希函数的函数对象。它将key作为参数,并利用函数对象中的哈希函数返回类型为size_t的唯一哈希值。默认值为std::hash<key>。

  • 第4个参数,为等比函数的函数对象。它内部通过等比操作符’=='来判断两个key是否相等,返回值为bool类型。默认值是std::equal_to<key>。在unordered_map中,任意两个元素之间始终返回false。

2. 问题分析

对于unordered_map而言,当我们插入<key, value>的时候,需要哈希函数的函数对象对key进行hash,又要利用等比函数的函数对象确保插入的键值对没有重复。然而,当我们自定义类型时,c++标准库并没有对应的哈希函数和等比函数的函数对象。因此需要分别对它们进行定义。

因为都是函数对象,它们两个的实际定义方法并没有很大差别。不过后者比前者多了一个方法。因为等比函数的函数对象默认值std::equal_to<key>内部是通过调用操作符"=="进行等值判断,因此我们可以直接在自定义类里面进行operator==()重载(成员和友元都可以)。

因此,如果要将自定义类型作为unordered_map的键值,需如下两个步骤:

  • 定义哈希函数的函数对象;

  • 定义等比函数的函数对象或者在自定义类里重载operator==()。

3. 定义方法

本文所有案例在用g++编译时,需加上-std=c++11或者-std=c++0x;如果用VS编译,请选择2010年及以上版本。

为了避免重复,下文以讨论哈希函数的函数对象为主,参数4则是通过直接在自定义类里面对operator==()进行重载。

首先简要介绍一下函数对象的概念:在《C++ Primer Plus》里面,函数对象是可以以函数方式与()结合使用的任意对象。这包括函数名、指向函数的指针和重载了“operator()”操作符的类对象。基于此,我们提出3个方法。

3.1 方法1:std::function

方法1就是利用std::function为person_hash()构建函数实例。初始化时,这个函数实例就会被分配那个指向person_hash()的指针(通过构造函数实现),如下所示。

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

using namespace std;

class Person{
   
public:
	string name;
	int age;

	Person(string n, int a){
   
		name = n;
		age = a;
	}
	bool operator==(const Person & p) const 
	{
   
	   return name == p.name && age == p.age;
	}
};

size_t person_hash( const Person & p ) 
{
   
    return hash<string>()(p.name) ^ hash<int>()(p.age);
}

int main(int argc, char* argv[])
{
   
    //ERRO: unordered_map<Person,int,decltype(&person_hash)> ids;
    //ERRO: unordered_map<Person,int,person_hash> ids(100, person_hash );
    //OK: unordered_map<Person, int, decltype(&person_hash)> ids(100, person_hash );
    unordered_map<Person,
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值