unordered_multimap用法和运算符覆盖

时间:2012-04-12 01:08:29

标签: c++ implementation unordered-map

我需要为我的Note对象使用unordered_multimap,并且键将是我的对象的measureNumber成员。我正在尝试实现它as shown here但我被卡住了。

首先,我不明白为什么在使用它之前必须覆盖operator==。我也很困惑为什么我需要一个哈希以及如何实现它。 In this example here,这两件事都没有完成。

基于第一个例子,这就是我所拥有的:

class Note {
private:
    int measureNumber;
public:
    inline bool operator== (const Note &noteOne, const Note &noteTwo);
}

inline bool Note::operator ==(const Note& noteOne, const Note& noteTwo){
    return noteOne.measureNumber == noteTwo.measureNumber;
}

我不知道如何实现哈希部分。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

std::multimap基于已排序的二叉树,该树使用小于操作对节点进行排序。

std::unordered_multimap基于哈希表,哈希表使用哈希和相等操作来组织节点而不对它们进行排序。

排序或散列基于键值。如果对象是键,则需要定义这些操作。如果密钥属于intstring等预定义类型,则无需担心。

您的伪代码存在的问题是measureNumber是私有的,因此Note的用户无法轻松指定地图的密钥。我建议公开measureNumber或重新思考设计。 (度量数字真的是一个很好的关键值吗?我猜这是音乐符号。)

std::multimap< int, Note > notes;
Note myNote( e_sharp, /* octave */ 3, /* measure */ 5 );
notes.insert( std::make_pair( myNote.measureNumber, myNote ) );

如果使用std::multisetstd::unordered_multiset,对象可以同时为键,在这种情况下,您可能希望定义运算符重载(和可能哈希)。如果operator==(或operator<)是成员函数,则左侧变为this,右侧成为唯一参数。通常这些功能应该是非会员朋友。那么你就有了

class Note {
private:
    int measureNumber;
public:
    friend bool operator< (const Note &noteOne, const Note &noteTwo);
}

inline bool operator <(const Note& noteOne, const Note& noteTwo){
    return noteOne.measureNumber < noteTwo.measureNumber;
}

此类可与std::multiset一起使用。要执行基本查找,可以使用未初始化的值构造一个虚拟对象,但measureNumber除外 - 这仅适用于简单对象类型。

答案 1 :(得分:0)

  

我需要为我的Note对象和键使用unordered_multimap   将是我的对象的measureNumber成员。

好的 - 我不确定您是在追踪multisetunordered_multisetmultimap还是unordered_multimap。我知道您的标题是unordered_multimap,但您提供的链接会导致unordered_multiset。在选择容器时应该考虑很多因素,但是如果不进行分析,那么在没有分析的情况下表现最佳的第二次猜测是一项有风险的业务。

  

我不明白为什么在使用之前我必须覆盖运算符==。   我也很困惑为什么我需要一个哈希以及如何实现它。   在这个例子中,这两件事都没有完成。

您需要operator==std::hash,因为它们在unordered_multimapunordered_multiset内部使用。在您链接到的示例中,密钥的类型为int,因此已定义operator==std::hash<int>。如果您选择使用Note作为密钥,则必须自己定义。


如果您不需要经常更改元素,我建议您从multiset开始。如果您 希望能够在不删除和插入的情况下更改Note,我建议您删除measureNumber成为Note成员并使用{ {1}}。

如果您认为容器的multimap<int, Note>版本更符合您的需求,那么您仍然可以选择unordered_ vs set。如果您选择map(已从unordered_multimap<int, Note>移除measureNumber),则与您的关联示例一样,密钥为Note。因此,您无需为此工作定义任何特殊内容。如果您选择将int作为measureNumber的成员并使用Note,则unordered_multiset<Note>是关键,因此您需要做进一步的工作,例如

Note

这使您可以创建和使用#include <functional> #include <unordered_set> class Note; // Forward declaration to allow specialisation of std::hash<> namespace std { template<> class hash<Note> { public: size_t operator()(const Note &) const; // declaration of operator() to // allow befriending by Note }; } class Note { private: int measureNumber; public: // functions befriended to allow access to measureNumber friend bool operator== (const Note &, const Note &); friend std::size_t std::hash<Note>::operator()(const Note &) const; }; inline bool operator== (const Note &noteOne, const Note &noteTwo) { return noteOne.measureNumber == noteTwo.measureNumber; } std::size_t std::hash<Note>::operator()(const Note &note) const { return std::hash<int>()(note.measureNumber); } 。但是,我不确定 真的是你需要的;你甚至可以发现排序std::unordered_multiset<Note>最适合你。进一步研究和思考如何使用容器以及分析应该给出最好的答案。