为什么我不能将对象存储在unordered_set中?

Why can't I store my objects in an unordered_set?

本文关键字:unordered set 存储 不能 对象 为什么      更新时间:2023-10-16

我知道一个集合被排序,因此在不超载<运算符的情况下添加对象不允许说出哪个对象较小以保持容器排序。但是,我不明白为什么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中的类型,您需要为您的类型进行散列功能。对于常见类型,例如intstd::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;

关于基于哈希的容器的理论的良好阅读在这里

另外,不要忘记,您需要对someTypeoperator==超载,没有它 - 它也无法正常工作。

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上的代码