I feel exhausted when I try to use the unordered_map container with char* as the key (on Windows I use VS 2010). I know that I need to define my own comparison function for char* , which inherits from binary_function . The following is an example program.
#include<unordered_map> #include <iostream> #include <string> using namespace std; template <class _Tp> struct my_equal_to : public binary_function<_Tp, _Tp, bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return strcmp( __x, __y ) == 0; } }; typedef unordered_map<char*, unsigned int, ::std::tr1::hash<char*>, my_equal_to<char*> > my_unordered_map; //typedef unordered_map<string, unsigned int > my_unordered_map; my_unordered_map location_map; int main(){ char a[10] = "ab"; location_map.insert(my_unordered_map::value_type(a, 10)); char b[10] = "abc"; location_map.insert(my_unordered_map::value_type(b, 20)); char c[10] = "abc"; location_map.insert(my_unordered_map::value_type(c, 20)); printf("map size: %d\n", location_map.size()); my_unordered_map::iterator it; if ((it = location_map.find("abc")) != location_map.end()) { printf("found!\n"); } return 0; }
I insert the same line of C abc twice and look through it. The second insertion should fail, and there will be only one abc in unordered_map. However, the output size is 3. It seems that the comparison function does not work here.
In addition, I get another strange result about the find function, running the program many times, the search result even changes! Sometimes the string abc found, but other times abc not found!
Can someone help me with this? Your help is much appreciated!
++++++++++++++++++++++++++++++++++++++++++++++++++ +++ ++++++++++++++++++++++++++++++++++
Edit: after defining the hash function for char* its own, the program works correctly. The full program code is given below. Thanks to everyone.
#include<unordered_map> #include <iostream> using namespace std; template <class _Tp> struct my_equal_to : public binary_function<_Tp, _Tp, bool> { bool operator()(const _Tp& __x, const _Tp& __y) const { return strcmp( __x, __y ) == 0; } }; struct Hash_Func{ //BKDR hash algorithm int operator()(char * str)const { int seed = 131;//31 131 1313 13131131313 etc// int hash = 0; while(*str) { hash = (hash * seed) + (*str); str ++; } return hash & (0x7FFFFFFF); } }; typedef unordered_map<char*, unsigned int, Hash_Func, my_equal_to<char*> > my_unordered_map; int main(){ my_unordered_map location_map; char a[10] = "ab"; location_map.insert(my_unordered_map::value_type(a, 10)); char b[10] = "abc"; location_map.insert(my_unordered_map::value_type(b, 20)); char c[10] = "abc"; location_map.insert(my_unordered_map::value_type(c, 20)); printf("map size: %d\n", location_map.size()); my_unordered_map::iterator it; if ((it = location_map.find("abc")) != location_map.end()) { printf("found!\n"); } return 0; }
Note. Using char *, since the key type for unordered_map or other STL containers can be dangerous, the safe way (seems to be the only way): in the main function new or malloc block (for example, an array of strings c) in the heap and fill it with strings c. Insert these lines c in unordered_map. The allocated memory block is freed at the end of the main function (via delete or free ).