C ++ std :: unordered_map键自定义散列

时间:2016-12-14 11:52:13

标签: algorithm c++11 hash stl

我收到了以下test.cpp文件

#include <string>
#include <functional>
#include <unordered_map>
#include <iostream>

class Mystuff {
public:
   std::string key1;
   int key2;
public:
    Mystuff(std::string _key1, int _key2) 
        : key1(_key1)
        , key2(_key2)
    {}
};

namespace std {
template<>
struct hash<Mystuff *> {
    size_t operator()(Mystuff * const& any) const {
        size_t hashres = std::hash<std::string>()(any->key1);
        hashres ^= std::hash<int>()(any->key2);
        std::cout << "Hash for find/insert is [" << hashres << "]" << std::endl;
        return (hashres);
    }
};
}; /* eof namespace std */

typedef std::unordered_map<Mystuff *, Mystuff *>mystuff_map_t;

mystuff_map_t map;

int insert_if_not_there(Mystuff * stuff) {
    std::cout << "Trying insert for " << stuff->key1 << std::endl;
    if (map.find(stuff) != map.end()) {
        std::cout << "It's there already..." << std::endl;
        return (-1);
    } else {
        map[stuff] = stuff;
        std::cout << "Worked..."  << std::endl;
    }
    return (0);
}

int main(){
    Mystuff first("first", 1);
    Mystuff second("second", 2);
    Mystuff third("third", 3);
    Mystuff third_duplicate("third", 3);

    insert_if_not_there(&first);
    insert_if_not_there(&second);
    insert_if_not_there(&third);
    insert_if_not_there(&third_duplicate);

}

您可以使用g++ -o test test.cpp -std=gnu++11进行编译。

我不知道我做错了什么:哈希键控算法肯定有效,但出于某种原因(显然是 - 糟糕的 - 我做某事) ),third_duplicate也插入到地图中,而我希望它不是。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

IIRC无序容器需要operator==以及std::hash。没有它,我预计会出现编译错误。除了你的密钥实际上是MyStuff* - 指针,而不是值。

这意味着您将重复密钥存储为单独的项目,因为它实际上不是unordered_map的真实副本 - 它具有不同的地址,并且地址相等是{{1}的方式判断平等。

简单解决方案 - 改为使用unordered_map。您需要重载std::unordered_map<Mystuff,Mystuff>(或者IIRC的一些替代模板,类似于operator==,您可以专攻)。您还需要更改std::hash以接受值而不是指针。

不要过度使用C ++中的指针,尤其不是原始指针。对于pass-by-reference,更喜欢对指针的引用(这是指C ++特定含义&#34;引用&#34; vs.&#34;指针&#34;)。对于容器,正常的默认设置是直接使用内容类型,尽管在某些情况下您可能需要指针(或智能指针)。

我还没有彻底检查你的代码 - 可能会遇到的问题比我发现的还多。