STL unordered_map char*作为key 笔记

来源:互联网 发布:rime输入法 mac 编辑:程序博客网 时间:2024/06/05 18:26

最近在使用unordered_map临时存储数据时候,总是出现程序异常退出的情况,调试查找了好久才找到原因,特意写了一个小demo记录一下。

使用char* 作为key,需要重载相应的比较函数和hash函数,原因是:使用本身的比较函数,他比较的仅仅是两个指针的地址,而不是两个指针存放的地址,因此需要重载strcmp函数进行判断。hash也是,使用指针地址座位key进行hash的而不是指针存放的地址进行,所以需要传入一个字符串查找。

#include<unordered_map>#include <iostream>#include <string.h>using namespace std;struct  char_cmp {bool operator()( const char* a, const char* b)const {return strcmp(a, b) == 0;}};struct Hash_map{int operator()(const char* str)const{int seed = 131;int hash = 0;while(*str){hash = (hash * seed) + (*str);str ++;}return hash & (0x7FFFFFFF);}};struct  TestData{TestData(){memset(this,0,sizeof(*this));}char m_cData[20];int m_i;};typedef unordered_map<const char*,TestData*,Hash_map,char_cmp> TestMapT;TestMapT m_testMap;void testPrinfmapInfo(){        TestMapT::iterator it = m_testMap.begin();        for (; it != m_testMap.end();++it)        {                cout << " test char = "<<it->second->m_cData<<" ,i = "<<it->second->m_i<<endl;        }}void testMap(const char* teststr){if (teststr[0] == '/0'){return ;}TestMapT::iterator itF = m_testMap.find(teststr);if (itF != m_testMap.end()){if (NULL != itF->second){itF->second->m_i = 1;}return ;}TestData *pTestData = new TestData;if (NULL == pTestData){cout <<"pTestData is NULL"<<endl;return ;}strncpy(pTestData->m_cData,teststr,sizeof(pTestData->m_cData));pTestData->m_i = 0;if (!m_testMap.insert(std::make_pair(pTestData->m_cData,pTestData)).second){cout <<" testmap insert error"<<endl;delete pTestData;return ;}testPrinfmapInfo();TestMapT::iterator it = m_testMap.begin();for (; it != m_testMap.end();){if (NULL != it->second && it->second->m_i == 0){TestData* p = it->second;delete p;m_testMap.erase(it++);}else{it++;}}cout <<"test map end"<<endl;}int main(int argc, char** argv){testMap("a");testMap("a");return 0;}
今天的重点的 earse 这块,key存入一个字符串后从unordered_map中移除后在此find相同的字符串导致程序异常退出了,最后发现问题出现earse与释放空间的先后顺序上,看下面的代码
<pre name="code" class="cpp">if (NULL != it->second && it->second->m_i == 0){TestData* p = it->second;delete p;m_testMap.erase(it++);                                       }

满足条件进行value空间的释放,然后从m_testMap中进行移除,空间已经被释放,移除的时候找不到之前的地址,导致之前的地址成为非法的。等到再次对m_testMap进行同一个字符串操作的时候(find,insert),比较指针指向的地址的时候,指针指向了一块非法的地址,导致程序崩溃。为了正确的从m_testMap移除,修改成下面的方式即可。
if (NULL != it->second && it->second->m_i == 0){TestData* p = it->second;delete p;m_testMap.erase(it++);                                       }

以上代码 testMap("a");第一次调用完成 对m_testMap的插入和移除,第二次调用的时候,在find处出现异常导致崩溃。以上代码在windows下VS中测试,未再linux下测试。

以后对map相关移除时候,先移除再进行释放比较安全,并且STL操作中最好使用前置++,效率高

                                             
0 0