C++11新增了一类散列容器包括unordered_set, unordered_map, unordered_multiset, unordered_multimap, 即之前熟悉的hash_set, hash_map等。

这类容器底层以哈希表实现之,通过unordered_map介绍下这类容器的使用。

unordered_map 是一个模板类,需要我们提供5个魔板参数。依次为:key值的类型, value值的类型,hash函数, 等价函数, 容器分配器。其中后三个有默认参数,那我们是不是只需要提供前2个模板参数就可以使用了呢? 不一定。当我们使用的key为内置类型时(如int, double, float, string等),后面三个默认模板参数在STL内有其特化版本,故可以直接进行使用。可一旦你的类为自定义类型, 其中的hash和equal就得由你自己提供。其实也不难理解, 假设你的对象是一块石头,石头怎么进行hash, 石头怎么怎么比大小呢?编译器当然不知道,这就需要你告诉编译器。下面我们对这2种情况分别举例说明。

(一)、当key为内置类型:

unordered_map<string, int> m_map;

当key为内置类型, 仅需提供key与value的类型便可运用。 其中hash<string> 与 equal <int> 均有特化版本,分配器对整个容器进行内存管理,这三个参数均为默认参数。

(二)、当key为自定义类型:

  比如我们简单定义一个package类,里面仅有名字,电话2项数据。

class package
{
public:
string getName() const { return name; }
long long getPhone() const { return phone; } package(string m_name = , long long m_pNum = ); bool operator== (const package& p) const
{ return name == p.name &&
phone == p.phone;
} private:
string name;
long long phone;
};

然后将原生hash包装使用下:

namespace std
{
template<>
struct hash<package>
{
size_t operator() (const package& s) const noexcept
{
return hash<decltype(s.getName())>()(s.getName()) +
hash<decltype(s.getPhone())>()(s.getPhone());
}
}; // 间接调用原生Hash.
}

或者可以借助借助boost库的hash_value:

namespace std
{
template<>
struct hash<package>
{
size_t operator() (const package& s) const noexcept
{
auto t = make_tuple(s.getName(), s.getPhone());
size_t value = boost::hash_value(t);
return value; // make_tuple(s.getName(), s.getPhone()) 等价于 tuple<string, long long>()(s.getName(), s.getPhone())
}
}; // 间接调用原生Hash.
}

当我们把Hash函数(package的特化版本)和 等价函数 (操作符==重载)提供后, 便可使用自定义版本的unordered_map了:

unordered_map<package, int> m_map;

下面给出测试代码:

测试环境: VS2017

#include <iostream>
#include <unordered_map>
#include <string>
#include <algorithm>
//#include <boost/functional/hash.hpp> // 根据安装路径选择hash.hpp
#include <tuple> using namespace std; class package
{
public:
string getName() const { return name; }
long long getPhone() const { return phone; } package(string m_name = , long long m_pNum = ); bool operator== (const package& p) const
{ return name == p.name &&
phone == p.phone;
} private:
string name;
long long phone;
}; package::package(string m_name, long long m_pNum)
: name(m_name), phone(m_pNum) { } namespace std
{
template<>
struct hash<package>
{
size_t operator() (const package& s) const noexcept
{
return hash<decltype(s.getName())>()(s.getName()) +
hash<decltype(s.getPhone())>()(s.getPhone()); //auto t = make_tuple(s.getName(), s.getPhone());
//size_t value = boost::hash_value(t);
//return value; // make_tuple(s.getName(), s.getPhone()) 等价于 tuple<string, long long>()(s.getName(), s.getPhone())
}
}; // 间接调用原生Hash.
} int main()
{
unordered_map<package, int> m_map; package p1{ "Wang", };
package p2{ "Li", };
package p3{ "Zhang", };
package p4{ "Zhou", };
package p5{ "Wang", };
package p6{ "Wang", }; m_map[p1]++;
m_map[p2]++;
m_map[p3]++;
m_map[p4]++;
m_map[p5]++;
m_map[p6]++; cout << m_map.bucket(p1) << " ";
cout << m_map.bucket(p2) << " ";
cout << m_map.bucket(p3) << " ";
cout << m_map.bucket(p4) << " ";
cout << m_map.bucket(p5) << " ";
cout << m_map.bucket(p6) << " " << endl; return ;
}

本文转自:https://www.cnblogs.com/xiguas/p/9977933.html

c++ unordered_map 自定义key的更多相关文章

  1. STL: unordered_map 自定义键值使用

    使用Windows下 RECT 类型做unordered_map 键值 1. Hash 函数 计算自定义类型的hash值. struct hash_RECT { size_t operator()(c ...

  2. unorder_map 自定义KEY

    1. boost::unorder_map 实现自定义KEY // boostLibTest.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" ...

  3. zabbix自定义key

    zabbix自定义key 1.修改客户端配置文件 #vi /opt/zabbix/etc/zabbix_agentd.conf Include=/opt/zabbix/etc/zabbix_agent ...

  4. 自学Zabbix3.5.5-监控项item-User parameters(自定义key)

    为什么要自定义KEY,即User parameters功能 有时候我们想让被监控端执行一个zabbix没有预定义的检测,zabbix的用户自定义参数功能提供了这个方法.我们可以在客户端配置文件zabb ...

  5. Zabbix常用key和自定义key的讲解

    zabbix中常用到的几个key: 1.监控端口的:net.tcp.port[,3306],可以在服务器端对被监控端测试. /usr/local/zabbix/bin/ -s192.168.8.120 ...

  6. zabbix使用自定义key进行监控

    我的zabbix-server是安装在另一台虚拟机上的,用来监控下图中的这台虚拟机 先修改zabbix的客户端配置文件,增加UserParameter那行,这里我只是用来测试,所以就随便起了一个名为p ...

  7. zabbix 通过自定义key完成网卡监控

    创建执行脚本: # cat /etc/zabbix/monitor_scripts/network.sh #!/bin/bash #set -x usage() { echo "Useage ...

  8. zabbix 自定义 key (转)

    转自:http://www.cnblogs.com/miclesvic/p/6164303.html 1.在zabbix_agent端zabbix_agentd.conf配置文件中增加自定义Key(/ ...

  9. 监控服务器cpu、磁盘、模板以及自定义key

    一.检测主机存活 net.tcp.service.perf[tcp,,] Float型 返回0代表端口挂了 zabbix fping要开启sudo权限之类比较不方便 二.监控CPU负载 监控load ...

随机推荐

  1. maven 标签: 项目管理软件 2016-09-11 22:29 323人阅读 评论(24) 收藏

    开始接触itoo的java项目之后,也就开始接触maven,搭建环境中有一个步骤是配置maven和jboss,当时知道jboss是用来部署我们的项目的,但是maven就只知道一个更新maven,那么, ...

  2. 《C程序设计语言》笔记(二)

    四:函数与程序结构 1:函数之间的通信可以通过参数.函数返回值以及外部变量进行. 2:如果函数定义中省略了返回值类型,则默认为int类型.如果没有函数原型,则函数将在第一次出现的表达式中被隐式声明,比 ...

  3. Docker镜像部分详解

    拉取镜像: docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] Docker 镜像仓库地址:地址的格式一般是 [:端口号].默认地址是 Docke ...

  4. 2018-9-4-Roslyn-通过-nuget-统一管理信息

    title author date CreateTime categories Roslyn 通过 nuget 统一管理信息 lindexi 2018-09-04 08:55:19 +0800 201 ...

  5. oracle函数 decode(条件,值1,翻译值1,值2,翻译值2,...值n,翻译值n,缺省值)

    [功能]根据条件返回相应值 [参数]c1, c2, ...,cn,字符型/数值型/日期型,必须类型相同或null 注:值1……n 不能为条件表达式,这种情况只能用case when then end解 ...

  6. oracle函数 LPAD(c1,n[,c2])

    [功能]在字符串c1的左边用字符串c2填充,直到长度为n时为止 [参数]C1 字符串 n 追加后字符总长度 c2 追加字符串,默认为空格 [返回]字符型 [说明]如果c1长度大于n,则返回c1左边n个 ...

  7. Win7如何显示文件后缀

    有些时候,我们需要修改文件的后缀名,但是Windows7系统默认不显示文件后缀.我们怎样显示和修改文件后缀呢?请接着往下看. 工具/原料   一个win7系统 方法/步骤   1 如图所示,此时是无法 ...

  8. 2012年NOIP普及组复赛题解

    题目涉及算法: 质因数分解:入门: 寻宝:模拟: 摆花:动态规划: 文化之旅:搜索. 质因数分解 题目链接:https://www.luogu.org/problem/P1075 这道题目只需要开个 ...

  9. Python--day49--ORM框架SQLAlchemy之relationship的使用(有时间要从新看,这里状态不好,没有仔细听)

    小贴士:   迭代器:只有在循环的时候才一个一个往外拿 relationship

  10. 递归求gcd(a,b)

    int gcd(int a,int b) { ) return a; else return gcd(b,a%b); }