linux下C++ STL hash_map的使用以及使用char *型变量作为Key值的一大“坑”
template<class _Key, class _Tp, class _HashFn = hash<_Key>,
class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> >
class hash_map
{
//内容定义
}
其中的_Key当然是你使用的hash的关键字。用它可以唯一确定一个hash节点。_Tp是hash中存放的节点内容的类。_HashFn是hash_map的散列函数,默认采用hash<Key>这个模版函数,后面会详细说明。_EqualKey是hash的匹配函数,缺省使用系统定义的equal_to, 会在后面详细说明。_Alloc是容器的空间配置器,空间配置器一般不需要自己指定,也不赞成自己指定的空间配置器。这不是本文讨论的重点内容,在这篇文章中有我实现仿造源代码实现了一个空间配置其,里面注释很详细,有兴趣可以看下:http://www.cnblogs.com/zxtp/p/4975888.html。
如果你想要写使用hash_map容器,应该这样定义:
hash_map<int, int> Hash;
当然,其中的_Key与_Tp参数也可以是你想要的任何类型,包括字符串、结构体、类等。只是需要你多做一些事情(后面会详细介绍)。hash_map中默认支持如下几种类型:
char、char *、const char *、unsigned char、signed char、short、unsigned short、int、unsigned int、long、unsignd long。
也就是说你使用这几种类型作为参数时,不需要做其它工作。
在hash_map中进行插入有三种方式,都是把它封装成对象的形式。如下:
Hash[] = ;
Hash.insert(hash_map<int, int>::value_type(, ));
Hash.insert(pair<int, int>(, ));
三、在hash_map中常用的操作(以下的代码都是以创建的hash表为例)
1)、在hash_map的查询操作,如下:
hash_map<int, int>::iterator it; //创建一个迭代器变量
it = Hash.find(); //在表中查询Key值为100的节点
if(it != Hash.end()) //表示含有该元素,反之则没有
{
cout << "有该元素" << endl;
}
2)、在hash_map中的操作还有很多,这里只说了查找,这是因为本文后面会用到查找。其它的操作,网上很多例子,这里就不再做重复工作了。
四、如何使用其它自定义参数类型作为Key?
如何在hash中使用其它类型作为Key的参数呢?在hash_map中,如果你想使用自己定义的类型作为hash的Key值,那就需要你去实现它的散列函数和匹配函数。散列函数和比较函数都是对运算符"()"的重载,但是重载的内容不一样。具体例子如下:
页式内存管理中,如果需要得到某段内存中存放的内容,你需要两个量:一个是内存页数,一个是在该页的偏移量。假设这里为内存建立一个索要,就以这两个量来当作hash表的关键字,只要你给出这两个量我就能索引到内存的具体位置。我可以用如下的结构作为hash_map的Key值。
struct stIndex
{
public:
unsigned int uiPage;//内存页数
unsigned int uiOffset;//在该页的偏移量
};
然后需要重载散列函数,注意这个格式是固定的,你必须这样写,或者写在定义一个类,封装在类里面。实现如下:
//hash散列函数,重载"()"
struct stHash
{
size_t operator() (const stIndex& key) const
{
return key.uiPage;//这里我只用了其中一个字段作为其散列依据
}
};
这里的散列函数其实不是真正意义上的散列函数,因为在hash_map的后面,会做一次取模的运算。
还需要重载比较函数。其格式和上面一样,也是固定的。
//hash的Key值比对函数,重载"()"
struct stEqualKey
{
bool operator()(const stKey& Key1, const stKey& Key2) const
{
return Key1.uiPage == Key2.uiPage
&& Key1.uiOffset == Key2.uiOffset;
}
};
准备工作完成了,现在可以使用自定义类型作为hash的key值了。只是需要显示地指定你重载的hash函数和比较函数。像下面这样定义:
hash_map<stIndex, void *vpPointer, stHash, stEqualKey> Hash;
其它的操作都是一样的了,这里就不再赘述了。
五、hash_map的一大“坑”!
为什么说这是一大“坑”呢?请耐心往下看!
在hash_map中,你可能会有如下的定义:
hash_map<char *, string> Hash;//这里的内容使用string是为了区分出char *
这样的定义是没有错的,前面也说过,hash_map支持char *类型作为Key值。但是使用的时候就会出现一些意想不到的问题。如下:
char pszKey[] = "abc";
string sValue = "cdefg";
Hash[pszStr] = sValue;//插入到hash中,并且成插入了 hash_map<char *, string >::iterator it;
it = find("abc");//查找不到刚才插入的内容 it = find(pszKey);//能够查找到刚才插入的内容
为什么会出现这种情况呢?在hash_map的比较函数是这样实现的:
template <class _Tp>
struct equal_to : public binary_function<_Tp, _Tp, bool>
{
bool
operator()(const _Tp& __x, const _Tp& __y) const
{ return __x == __y; }
};
这里我们可以看到,它的比较模版函数传入的类型是创建hash_map时传入的第一个参数,也就是说我们写
hash_map<char *,string > Hash;
的时候就已经把这个参数定义为了一个char *型的地址,在传入重载的函数中传入的只是一个地址,也就是char *型的参数,在比较的时候,比较的也只是地址而已。所以 it = find("abc"); 这样查找是查找不到的。如果在程序中一定要使用char *作为Key时,只有重载比较函数。而这个在STL中并没用进行说明。也许STL的本意是更本不支持地址类型。
linux下C++ STL hash_map的使用以及使用char *型变量作为Key值的一大“坑”的更多相关文章
- 在阿里云linux下使用SVN访问VisualSVN出错:SSL handshake failed: SSL error: Key usage violation in certificate has been detected
Subversion clients receive the following error message when attempting to connect to VisualSVN Serve ...
- Linux下的Shell编程
从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁.用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操 ...
- Linux下C程序的编辑,编译和运行以及调试
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...
- linux下JDK,tomcat的安装与环境变量配置
先从网上下载jdk(jdk-1_5_0_02-linux-i586.rpm) ,下载后放在/home目录中,当然其它地方也行. 进入安装目录#cd /home#cp jdk-1_5_0_02-linu ...
- socket在windows下和linux下的区别
原文:socket在windows下和linux下的区别 1)头文件 windows下winsock.h/winsock2.h linux下sys/socket.h 错误处理:errno.h 2 ...
- Linux 下V4l2摄像头采集图片,实现yuyv转RGB,RGB转BMP,RGB伸缩,jpeglib 库实现压缩RGB到内存中,JPEG经UDP发送功(转)
./configure CC=arm-linux-gnueabihf-gcc LD=arm-linux-gnueabihf-ld --host=arm-linux --prefix=/usr/loca ...
- Linux下onvif客户端获取h265 IPC摄像头的RTSP地址
1. 设备搜索,去获取webserver 的地址 ,目的是在获取能力提供服务地址,demo:https://www.cnblogs.com/croxd/p/10683429.html 2. GetCa ...
- 重要:Linux下IDE--KDevelop (用来跟踪调试C++) Ubuntu下QT4开发环境的搭建及初体验
Linux下安装Qt4有两大问题,一是环境变量,二是IDE(集成开发环境).安装Qt4也有两种方法,一种是apt-get,一种是下载源码包,而后 一种方法已经人证实是最有可能不好使的方法.所以我最终采 ...
- Linux下的Shell编程(2)环境变量和局部变量
Shell Script是一种弱类型语言,使用变量的时候无需首先声明其类型. 局部变量在本地数据区分配内存进行存储,这个变量归当前的Shell所有,任何子进 程都不能访问本地变量.这些变量与环境变量不 ...
随机推荐
- Xcode的代码片段快捷方式-Code Snippet Library(代码片段库)
最近换了新电脑,装上Xcode敲代码发现很多以前攒的Code Snippet忘记备份了,总结了一下Code Snippet的设置方法,且行且添加,慢慢积累吧. 如下图: Title - Code ...
- Linux安装系统注意事项及系统初始化
Linux安装系统注意事项 1.分区 学习用途: /boot:200M /swap :内存的1到2倍 /:根据需要分配大小,比如虚拟机下总空间是15G,那么可以分配8——10G跟/分区,如果是生产 ...
- HTTP的一些基础知识
HTTP是计算机通过网络进行通信的规则.http是一种无状态协议:不建立持久的连接,服务端不保留连接信息. 一个完整的HTTP请示,通常用7个步骤:1.建立TCP连接2.Web浏览器向Web服务器发送 ...
- 第二章IPC——IPC与开启多进程
问题 一.IPC ①.什么是IPC ②.为什么要有IPC 二.多进程 ①.如何开启多进程 ②.系统如何创建多进程 三.多进程引发的问题 问:私有进程(利用":+进程名")能否共 ...
- 深入 char * ,char ** ,char a[ ] ,char *a[] 内核
本文来自CSDN博客:daiyutage的文章 来源网页地址:http://blog.csdn.net/daiyutage/article/details/8604720 本人觉得这是一编很有价值的文 ...
- linux服务器之间拷贝文件和文件夹
传输文件用法:scp 本机文件目录 远程服务器用户名@服务器IP:/服务器目录 示例:
- IE6 js修改img的src属性问题
今天在做项目,有个点击按钮切换图片功能,即修改img的src属性,在IE6下测试,切换图片不显示,右键选择显示图片,可以显示出来,琢磨了很久,最终发现是因为该按钮是a标签导致的, 随后上网查了下,有些 ...
- DeflateStream类
DeflateStream是另外一种压缩与解压缩流,使用方法与GZipStream类似,而且压缩之后的带下也差不多. 一.属性 BaseStream 获取对基础流的引用. CanRead 获取一个值 ...
- TCP连接探测中的Keepalive和心跳包. 关键字: tcp keepalive, 心跳, 保活
1. TCP保活的必要性 1) 很多防火墙等对于空闲socket自动关闭 2) 对于非正常断开, 服务器并不能检测到. 为了回收资源, 必须提供一种检测机制. 2. 导致TCP断连的因素 如果网络正常 ...
- perl 爬取csdn
<pre name="code" class="python">use LWP::UserAgent; use POSIX; use HTML::T ...