【发布时间】:2013-12-18 04:51:08
【问题描述】:
在尝试使用容器unordered_map 和char* 作为键时,我感到筋疲力尽(在Windows 上,我使用的是VS 2010)。我知道我必须为char* 定义我自己的比较函数,它继承自binary_function。下面是一个示例程序。
#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;
}
我插入相同的 C 字符串 abc 两次并查找它。第二次插入应该会失败,并且 unordered_map 中将只有一个 abc。但是输出的大小是3,这里的比较功能好像不能正常工作。
另外,我得到了另一个关于find函数的奇怪结果,通过多次运行程序,发现结果甚至发生了变化!有时会找到字符串abc,而有时找不到abc!
有人可以帮我解决这个问题吗?非常感谢您的帮助!
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++
编辑:我自己为char* 定义了一个哈希函数后,程序可以正常工作。下面列出了完整的程序代码。谢谢大家。
#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;
}
注意:使用 char* 作为 unordered_map 或其他 STL 容器的键类型可能很危险,安全的方法(似乎是唯一的方法)是:在 main 函数中,new 或malloc堆上的一个块(例如一个c字符串数组)并用c字符串填充它。将这些 c 字符串插入 unordered_map。分配的内存块在 main 函数结束时被释放(delete 或 free)。
【问题讨论】:
-
你不需要从
binary_function继承。它甚至可能被弃用;我现在查不出来。 -
这不是问题,但是包含两个连续下划线的名称(
__x、__y)和以下划线后跟大写字母(_Tp)的名称被保留到实现(编译器及其库)。不要使用它们。 -
你的意思是指向
char*的键字符串可以改变吗?因为我认为您希望 key 是const char *指向的常量字符串。让char *到const char *的每一次出现都支持这一点 -
@rahul.deshmukhpatil 还有更深层次的问题,请看一下答案和下面的cmets。
-
只是一个注释,你会想
#include <functional>为binary_function。