为什么我不能将对象存储在unordered_set中?
Why can't I store my objects in an unordered_set?
我知道一个集合被排序,因此在不超载<
运算符的情况下添加对象不允许说出哪个对象较小以保持容器排序。但是,我不明白为什么unordered_set
无法做到这一点。
如果我尝试这样的事情:
#include <iostream>
#include <string
#include <unordered_set>
struct someType{
string name;
int code;
};
int main(){
std::unordered_set <someType> myset;
myset.insert({"aaa",123});
myset.insert({"bbb",321});
myset.insert({"ccc",213});
return 0;
}
我遇到了几个错误:
c: qt qt5.1.0 工具 mingw48_32 lib lib gcc i686-w64-Mingw32 4.8.0 include c bits bits bit hashtable_policy.h:1070:error for Invalid类型'struct std :: hash'
:hash'错误:呼叫'std :: unordered_set :: unordered_set()'
没有匹配功能c: qt qt5.1.0 工具 mingw48_32 lib lib gcc i686-w64-mingw32 4.8.0 include c bits c bits hashtable_policy.h:1103:oror:no for Call to Call to to to'(const std :: hash)(const wory stype&amp;)'
c: qt qt5.1.0 工具 mingw48_32 lib lib gcc i686-w64-mingw32 4.8.0 include c bits bits stl_function.h:208:208:error for'运算师='(操作数类型是'const wordy stype'和'const wordy stype')
为什么要修复它?
要使用Unordered_set或unordered_map中的类型,您需要为您的类型进行散列功能。对于常见类型,例如int
或std::string
-标准库提供哈希功能。对于您的类型,您可以超载标准std::hash
,因此可以:
namespace std {
template <> struct hash<someType> {
size_t operator()(const someType & x) const {
std::hash<std::string> h;
return h(x.name);
// or simply return x.code
// or do something more interesting,
// like xor'ing hashes from both members of struct
}
};
}
另一种方法是用超载的operator()
提供自己的类型,并将其作为unordered_set中的哈希模板参数列出,例如:
struct someTypeHasher {
size_t operator()(const someType& x) const {
return x.code;
}
};
std::unordered_set<someType, someTypeHasher> myset;
关于基于哈希的容器的理论的良好阅读在这里
另外,不要忘记,您需要对someType
的operator==
超载,没有它 - 它也无法正常工作。
如 starl1ght 给出的答案所述,您需要为someType
提供哈希函数。但是,我将通过该哈希功能结合您班级的所有成员。否则,例如,如果相同的 name
发生频率相同,但具有不同的code
值,您可能会得到很多碰撞。要创建哈希功能,您可以使用 boost ,但也可以手工制作。
starl1ght 还提到,您需要对someType
超载operator==
,但是您也可以定义一个单独的比较功能,并将其提供给unordered_set
。此外,您可以使用lambda表达式,而不是定义哈希和比较功能。如果您将所有内容放在一起,那么您的代码可以如下写:
auto hash = [](const someType& st){
return std::hash<std::string>()(st.name) * 31 + std::hash<int>()(st.code);
};
auto equal = [](const someType& st1, const someType& st2){
return st1.name == st2.name && st1.code == st2.code;
};
std::unordered_set<someType, decltype(hash), decltype(equal)> myset(8, hash, equal);
IDEONE上的代码
- 为什么我无法更改"set<set>"循环中的值<int>
- 对于set上的循环-获取next元素迭代器
- 在声明中合并两个常量"std::set"(不是在运行时)
- 有没有办法对std::unordered_set、std::unrdered_map、std::set、std::map
- 将 std::set 与基于键的比较器一起使用
- 如何使用set实现无序数据结构?
- 使用运算符调用 void 函数时出错<set>
- 修改"std::set"中用户定义类型的值
- 生成提升::hana::set 的常量表达式问题
- 如何在构造函数参数中初始化"std::set"?
- 如何使用 lower_bound/upper_bound 从 std::set 获取索引号?
- 如何在 C++ 中转发声明 std::set?
- 重构使用动态强制转换的 std::set 的比较运算符
- set::find 查找不存在的元素
- 为什么 std::set.erase(first, last) 会影响从中获取 (first, last) 的容器?
- 将 std:set<int32_t> 复制到 std::set <uint32_t>的好方法
- 错误 C2676:std::set::const_iterator 没有运算符 + 函数?
- std::set 是否将对象连续存储在内存中?
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- google test PrintTo for std::set<std::string>