我可以使用成员变量作为 hash_set/hash_map 的键吗?

Posted

技术标签:

【中文标题】我可以使用成员变量作为 hash_set/hash_map 的键吗?【英文标题】:Can I use a member variable as a key to a hash_set/hash_map? 【发布时间】:2011-04-23 22:41:17 【问题描述】:

我有这样的课:

class Foo

   long long Id;
   string x;
   string y;
   // other member variables and functions
;

我想将它存储在hash_set(或hash_map)中,但使用Id 成员变量作为插入和搜索的键。我不确定我该怎么做。我想了以下几种方法,但都不是很好:

1) 我可以编写一个自定义散列函数,该函数将使用 Id 散列对象,但是我不能使用 hash_set 上的 find() 方法按 Id (long long) 查找项目,因为它将需要传入 Foo 对象。

2) 我可以复制 Id 并创建一个hash_map<long long, Foo> 而不是 hash_set<long long, Foo> 但我有 1 亿个这些对象的实例,所以我宁愿不复制 Id 字段。

3) 我可以将 Id 字段移到 Foo 之外,然后执行 hash_map<long long, Foo>,但这会有点混乱,因为 Id 是由班级内部使用的,最好将其保留在 @987654332 @。

有什么想法吗?我正在寻找的是一种存储 Foo 对象但能够使用 long long (按 ID)在 hash_set 中搜索它们的方法。

谢谢!

【问题讨论】:

这个的使用模式是什么?您是设置一次然后只读取它还是继续修改设置? 【参考方案1】:

这可能不是一个特别优雅的解决方案,但它确实有效:为您的类定义一个 operator <(以及 operator ==,正如 CashCow 建议的那样),该类根据 Id 字段对对象进行排序,然后当您想做一个find,传入一个包含你正在寻找的Id的虚拟对象。

【讨论】:

适用于标准集或地图,但不适用于基于散列的容器。 operator <,我的意思是。 为什么不呢?我认为基于哈希的容器仍然依赖operator < 来最终确保两个对象相等。 hash_mapunordered_map 似乎都采用比较函子来表示相等,不少于。 似乎unordered_map使用equal_to<Key>进行比较,但至少VC++的hash_map使用hash_compare<Key, less<Key>> 也只是重载相等运算符。对于散列函数本身,只需返回 id。【参考方案2】:

如果您没有找到 hash_set/hash_map 容器的实际解决方案,您可能需要考虑使用 uthash 哈希表实现,它直接支持您的用例。虽然它是 C 语言并且它基于宏,但它是现有的最流行的哈希表实现之一。

【讨论】:

【参考方案3】:

我没有太多经验,但是 boost::multiindex 默认建立在 boost::hash 之上,并且明确支持仅使用在对象中找到的键在哈希中查找对象.

【讨论】:

【参考方案4】:

选项 2 是您给出的三个选项中的最佳选择。如果你愿意的话,你可以编写一个自定义的 hash_set(甚至只是一个常规的包装器)来提供你想要的东西。在这种情况下,我更喜欢选项 1。您可以轻松添加一个仅获取键值的 find 函数,并对其进行调整以正确使用内部 find 函数,从而为您带来所有好处。

【讨论】:

【参考方案5】:

1) 我可以编写自定义哈希函数 这将使用散列对象 Id,但是我不能使用 find() hash_set 上的方法来查找项目 按 ID(长长),因为它会 需要传入一个 Foo 对象。

这是标准地图和集合容器的常见问题。添加一个构造函数或静态成员来创建一个比较对象,一个只有键成员有效的对象。

【讨论】:

以上是关于我可以使用成员变量作为 hash_set/hash_map 的键吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我可以在 Qt 5.5.1 中使用 QSerialPort* 作为临时变量而不是作为类的成员?

深度学习之序列处理

对象作为成员变量

类作为成员变量类型使用接口作为成员变量类型使用接口作为方法的参数或返回值使用

将声明的枚举转发为类成员变量

effective STL