2012-04-12 120 views
0

我需要为我的Note对象使用unordered_multimap,而这些键将是我的对象的measureNumber成员。我试图执行它as shown here但我卡住了。unordered_multimap用法和操作符覆盖

首先,我不明白为什么我必须覆盖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; 
} 

我不知道如何实现,虽然散列部。有任何想法吗?

回答

1

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除外 - 这仅适用于简单对象类型。

+0

我将如何构建多图,像这样? 'multimap noteMap;'运算符<'函数的定义是在头文件还是在实现文件中? – networkprofile 2012-04-12 01:29:04

+0

@Sled好的,我希望这是你要找的。现在需要走了,祝你好运! – Potatoswatter 2012-04-12 01:41:02

+0

我有getter和setter为measureNumber,所以这不是一个真正的问题。我现在认识到,除了特定的笔记之外很难删除,因为它们是通过measureNumber进行映射的,但我需要这种模型进行实时合成,因为我需要尽快地通过度量来找到笔记,这看起来像是一个迄今为止的好方法。 (我不得不多次改变事情)非常感谢您的帮助! – networkprofile 2012-04-12 01:56:09

1

我需要为我的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 s没有删除和插入,我建议删除measureNumber作为Note成员和使用multimap<int, Note>

如果您觉得​​版本的容器更适合您的需求,您仍然有setmap的选择。如果您选择unordered_multimap<int, Note>(已从Note中删除measureNumber),则正如在您的链接示例中,密钥为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>。但是,我不确定这个是否真的是你需要的;你甚至可以发现排序的std::vector<Note>最适合你。进一步的研究和想法,你将如何使用你的容器与分析应该给出最好的答案。