首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

使用std:地图发现的一个容易忽略的小疑点

2013-03-27 
使用std::map发现的一个容易忽略的小问题最近在使用的std::map的过程中发现了一个小问题,折腾了半天之后才

使用std::map发现的一个容易忽略的小问题

最近在使用的std::map的过程中发现了一个小问题,折腾了半天之后才发现自己忽略了一个地方。相信也有人遇到和我一样的情况,在这里做个记号,将问题和解决办法和大家共享一下。这里有一个函数,暂且叫做getMap(),是Doc类中的一个类成员函数。getMap返回一个std::map,具体的类型定义如下:

std::map<const char*,const char*>map_;

此map有一堆键值:family_seniority=shen;键值的类型都是const char*。于是我在main函数里试图调用getMap取到这个map,进而取到这个map里面的family_seniority键的值。但是,就在这里问题来了,运行之后我的程序崩溃了,然后单步调试请看下面的图。

使用std:地图发现的一个容易忽略的小疑点

事实证明我想要的这个std::map已经成功返回了,而且还带入了我想要的值,接下来我试图把这个index为0的一对键值取出来:

const char* strss = map_["family_seniority"];

然后我 std::cout << strss << std::endl;尝试输出,结果程序崩溃了,于是我把断点打在这句输出的代码上,调试的结果大吃一惊:

使用std:地图发现的一个容易忽略的小疑点

怎么map里面有两对键值了,怎么会这样?我一下子蒙了,我没有做任何操作啊。我在调用getMap()方法之后获得map之后就立即const char* strss = map_["family_seniority"];有了这句,再下面一句就是输出,应该就是这三句之间的某句代码有问题了。我尝试进入getMap()函数,发现map返回的时候也是只有一对键值,那么问题肯定就是出现在const char* strss = map_["family_seniority"];这句代码上。但是我想了之后,这只是一个简单的取键值得操作,怎么会出现这个问题,但是我查看了文档之后才发现,当使用operator[]操作取键值时会自动在整个map里查找一次,如果发现了有family_seniority这个键,就返回这个键相对应的值,如果没有则在map里插入这个键。问题又来了,我的map里明明是有这个family_seniority键的呀,怎么还会插入一条呢?

于是我再检查了下我的map定义:std::map<const char*,const char*>map_;恍然大悟,我的模板参数是const char*,是指针。也就是说实际上在map里面把指针地址作为了键,并没有把指针所指的内容family_seniority作为键。从第二张图看到,两个键的地址为0x000eb3c8,0x00cb1dd8,这根本就是两个不同的地址,再operator[]内的查找过程中,0x000eb3c8 != 0x00cb1dd8。这样问题的原因也就找到了,由于是将字符串指针作为了地址,因此当使用operator[]取family-seniority值,只是在map里查找地址,发现没有所要取的地址,于是就插入了一条,这样也就导致了strss为0x00000000,。

再往更深层次追求就发现,上面的这个理由略微有点牵强,为什么呢?因为我们知道,map是一个模板类,这个模板类有四个参数,请看map的申明:

发现键的顺序已经是从小到大排列了,也就说说明map确实是默认小于排列的。但是这仅仅都是针对那些可以比较的数据类型,虽然指针也是可比较的,但是我们想比较的是指针所指向的内容,若与传入的键命相等,则取出该键的值,这样在operator[]过程中就涉及到一个查找一个一比较过程,而且要求比较的不能是地址,而是地址中的内容。从map的申明可以看出,_Pr是给了默认值,在map内部有:

typedef _Pr key_compare;

typedef _Tree<_Tmap_traits<_Kty, _Ty, _Pr, _Alloc, false> > _Mybase;

再看map中的函数:

class sort{public:bool operator()(const char* str1, const char* str2){return strcmp(str1, str2) < 0;}};//std::map<const char*,const char*,sort>map_;std::map<const char*,const char*,sort> map_ = pDoc->getMap();const char* strss = map_["family_seniority"];std::cout << strss << std::endl;
OK!成功取到了family_seniority键的值!虽然不是很大的问题,但是我觉得还是一个容易忽略的地方,一旦std::map中的键位指针时,此时就要考虑默认的less能否将指针的内容取出进行比较,从而顺利取到键值,答案是不确定的。此方法还使用当键位结构体或者类时,也可以传入外部的自实现比较函数,从而达到目的。

热点排行