c++STL中的hash_map自定义类。
2016-01-26 01:18
357 查看
是的,hash_map是一个很方便的容器,有了STL确确实实给了C++developer很大方便,hash_map就是其中一种。他在数据少的时候,作用和基于RB-tree的map差不多,甚至不如,毕竟有hasher。但是在大量数据的时候,就很快捷了。我平时用hash_map都是用基本类型的,最多弄个string类,也是库里已经弄好了的。直接套模板就行。可是今天遇到一个问题就是当你需要把一个自定义类作为key的时候,应该怎么办?当我写完程序并编译的时候,他报错了,报了很长的一段错。前两行是这样的:
error C2784: “bool std::operator <(const std::list<_Ty,_Alloc> &,const std::list<_Ty,_Alloc> &)”: 未能从“const Box”为“const std::list<_Ty,_Alloc> &”推导 模板 参数
e:\program files\vc\include\list(1958) : 参见“std::operator <”的声明
然后我根本不知道这是什么问题,只好百度,百度里基本说到都是忘记使用#include<string>,然而这并不是问题的关键,因为我并没有用到字符串啊,就是加上也是一样报错。
终于我耗时1h才找到只言片语,又回头看看错误报告,似乎是<的原因?没有重载?是了,因为hash_map实现的时候需要用less也就是<函数来对key排序,那就把<重载了
bool operator<(const Box &k2)const
{
if ((*this).width != k2.width)
{
return (*this).width < k2.width;
}
if ((*this).depth != k2.depth)
{
return (*this).depth < k2.depth;
}
if ((*this).height != k2.height)
{
return (*this).height < k2.height;
}
return false;
}
那么应该可以了吧?结果还是报错:
1>e:\program files\vc\include\xhash(30): error C2440: “类型转换”: 无法从“const Box”转换为“size_t”
1> 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
那么是跟size_t有关喽,又用了1h我终于知道问题所在了,http://www.cplusplus.com/中的定义是这样的
然后详细情况如下:
是的少了个hasher,在《STL源码剖析》中,阐明了只有基本类型和字符指针可以调用默认hash函数。在使用了其他类型时(比如自定义类)用户必须为其自定义一个hash函数像这样:size_t operator() (const Box& b)const放在一个结构体中,作为仿函数,也就是函数对象。
我个人在这是这样实现hasher的:
size_t operator() (const Box& b)const
{
return (b.depth + 10 * b.height + 100 * b.width) % 20;
};
本来以为总算可以了,然后还是报错:1>e:\program files\vc\include\xhash(264): error C2039: “bucket_size”: 不是“cmp_key”的成员
1> c:\users\administrator\documents\visual studio 2013\projects\最高的箱子\最高的箱子\源.cpp(47) : 参见“cmp_key”的声明
是的,真烦,bucket_size是什么鬼啊,继续查资料。。。
终于,我找到了,在http://www.cplusplus.com/中的定义是这样的:
虽然是unordered_map不过定义应该差不多吧。而在stackoverflow中,大神是这么说的:
在《STL源码剖析》中,是这么说buckets的:hashTable表格内的元素为桶子(bucket),就是说表格内的每个单元,涵盖的不只是个节点,甚至可能是一“桶”节点。
这就很明了了,我们可以在结果中加上:
enum
{ // parameters for hash table
bucket_size = 4, // 0 < bucket_size
min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N
};
必不可少的。然而还是报错:
1>e:\program files\vc\include\xhash(744): error C2064: 项不会计算为接受 2 个参数的函数
1> 类不会将“operator()”或用户定义的转换运算符定义到指向函数的指针或指向函数的引用(它们接受适当数量的参数)
恩,重载<在此时来说是不行的,需要在结构体中加上:
bool operator()(const Box &k1, const Box &k2)const
{
if (k1.width != k2.width)
{
return k1.width < k2.width;
}
if (k1.depth != k2.depth)
{
return k1.depth < k2.depth;
}
if (k1.height != k2.height)
{
return k1.height < k2.height;
}
return false;
}
依然是仿函数,而不是重载运算符作为equalToKey()。这样就全部完成了,全部代码在这:http://blog.csdn.net/youngstunner/article/details/50583852
完整的实现了一个自定义类的hash_map,大功告成!
error C2784: “bool std::operator <(const std::list<_Ty,_Alloc> &,const std::list<_Ty,_Alloc> &)”: 未能从“const Box”为“const std::list<_Ty,_Alloc> &”推导 模板 参数
e:\program files\vc\include\list(1958) : 参见“std::operator <”的声明
然后我根本不知道这是什么问题,只好百度,百度里基本说到都是忘记使用#include<string>,然而这并不是问题的关键,因为我并没有用到字符串啊,就是加上也是一样报错。
终于我耗时1h才找到只言片语,又回头看看错误报告,似乎是<的原因?没有重载?是了,因为hash_map实现的时候需要用less也就是<函数来对key排序,那就把<重载了
bool operator<(const Box &k2)const
{
if ((*this).width != k2.width)
{
return (*this).width < k2.width;
}
if ((*this).depth != k2.depth)
{
return (*this).depth < k2.depth;
}
if ((*this).height != k2.height)
{
return (*this).height < k2.height;
}
return false;
}
那么应该可以了吧?结果还是报错:
1>e:\program files\vc\include\xhash(30): error C2440: “类型转换”: 无法从“const Box”转换为“size_t”
1> 没有可用于执行该转换的用户定义的转换运算符,或者无法调用该运算符
那么是跟size_t有关喽,又用了1h我终于知道问题所在了,http://www.cplusplus.com/中的定义是这样的
然后详细情况如下:
是的少了个hasher,在《STL源码剖析》中,阐明了只有基本类型和字符指针可以调用默认hash函数。在使用了其他类型时(比如自定义类)用户必须为其自定义一个hash函数像这样:size_t operator() (const Box& b)const放在一个结构体中,作为仿函数,也就是函数对象。
我个人在这是这样实现hasher的:
size_t operator() (const Box& b)const
{
return (b.depth + 10 * b.height + 100 * b.width) % 20;
};
本来以为总算可以了,然后还是报错:1>e:\program files\vc\include\xhash(264): error C2039: “bucket_size”: 不是“cmp_key”的成员
1> c:\users\administrator\documents\visual studio 2013\projects\最高的箱子\最高的箱子\源.cpp(47) : 参见“cmp_key”的声明
是的,真烦,bucket_size是什么鬼啊,继续查资料。。。
终于,我找到了,在http://www.cplusplus.com/中的定义是这样的:
虽然是unordered_map不过定义应该差不多吧。而在stackoverflow中,大神是这么说的:
在《STL源码剖析》中,是这么说buckets的:hashTable表格内的元素为桶子(bucket),就是说表格内的每个单元,涵盖的不只是个节点,甚至可能是一“桶”节点。
这就很明了了,我们可以在结果中加上:
enum
{ // parameters for hash table
bucket_size = 4, // 0 < bucket_size
min_buckets = 8 // min_buckets = 2 ^^ N, 0 < N
};
必不可少的。然而还是报错:
1>e:\program files\vc\include\xhash(744): error C2064: 项不会计算为接受 2 个参数的函数
1> 类不会将“operator()”或用户定义的转换运算符定义到指向函数的指针或指向函数的引用(它们接受适当数量的参数)
恩,重载<在此时来说是不行的,需要在结构体中加上:
bool operator()(const Box &k1, const Box &k2)const
{
if (k1.width != k2.width)
{
return k1.width < k2.width;
}
if (k1.depth != k2.depth)
{
return k1.depth < k2.depth;
}
if (k1.height != k2.height)
{
return k1.height < k2.height;
}
return false;
}
依然是仿函数,而不是重载运算符作为equalToKey()。这样就全部完成了,全部代码在这:http://blog.csdn.net/youngstunner/article/details/50583852
完整的实现了一个自定义类的hash_map,大功告成!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C#中遍历Hashtable的4种方法
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解