有没有一种方法可以将对对象的引用/指针保留在unordered_set中?

时间:2020-03-28 19:45:44

标签: c++ pointers reference stl unordered-set

我有两个class A对象。在其他class B中,我想保留class A的对象的无序集合。注意class B的对象因此包含一个集合,该集合可能指向与另一个集合相同的class A对象。要求这些class A对象绝不能复制或做任何其他事情,因为它们包含应该由class B和{{1的不同对象使用和更改(共享)的成员数据) }}。

首先,由于我来自C语言,因此我认为仅使用指向对象的指针作为集合中的值。但是,在编码后,我看到我现在还需要传递重写的哈希和相等功能,因为我必须比较类A的对象在class A的私有成员上的相等性。因此,散列函数必须是class A的公共成员函数。

但是我想知道,由于class A似乎引用了一个value_type 的引用,是否有可能仅将A用作std::unordered_set::insert()的值类型。这将使代码容易一些,因为默认情况下它将使用std::unordered_set中已实现的== operator。但是,我不确定class A是否将您传递的对象复制到其中。似乎没有,但是value_type仍然是A,而不是A&。

我也看不到std::unordered_set::insert()std::unordered_set::insert()之间的区别。我不明白“复制与移动”的含义。

TLDR:要在集合或映射中保留对用户定义类的对象的引用,在这种情况下是否可以将std::unordered_set::emplace()用作value_type?还是A*?还是只是普通的std::reference_wrapper<A>

这是一个最小的可重现示例:

A

1 个答案:

答案 0 :(得分:0)

免责声明:我是OP,并且是C ++的新手。我的代码现在可以按预期的方式编译和运行,尽管我确实相信以下所有信息都是正确的,但是请留下评论以通知我任何错误。

对于那些感兴趣的人,我最终在A类中创建了两个公共函子(内部,因为我需要访问私有成员(也可以使用friend),并在声明中使用它们std::unordered_set。对于类型,我使用了A *。更好的解决方案可能是使用智能指针,但是我对此并不陌生,因此我尚未对其进行详细研究。

关于std::unordered_set,我了解了以下内容:

  1. 仅对列出的here类型实现默认的相等和哈希行为。
  2. 如果您还有其他需要,可以使用3种选择:使用某种类型的指针(例如原始std::shared_ptrstd::unique_ptr,...),使用std::reference_wrapper<T> ,或使用类型本身。请注意,不允许将A&之类的引用作为std::unordered_set的value_type,因此不允许将其作为包装器。
  3. 在前两个选项中,默认实现(如果有)不会“级联”以使用您可能为类型定义的任何operator ==。在第5点中,提出了解决方案。
  4. 在最后一个选项中,您类型的operator ==用作默认的“等号”。在这里只需要定义哈希器即可。但是,您应该警惕std::unordered_set::insert()会创建插入的元素的副本,因此,如果其中包含静态分配的成员数据,则应确保在开始复制该类型的实例时,程序仍能正常运行。我认为这是最不冗长的解决方案,也是我发现最多示例的解决方案。 (使用std::unordered_set::emplace()可能是解决整个复制问题的一种方法,但我还没有弄清楚。)
  5. 通常,可以通过两种方式提供“哈希器”和“等同”功能:通过定义std::hash<T>和/或std::equal_to<T>,或通过为此创建函子。有关如何执行此操作的更多信息here。这些基本上可以做同样的事情,因此可以互换。如第4点所述,当您存储直接类型时,还有另外一种选择,您也可以使用operator ==,然后在声明{{1}时无需指定任何'等号' }。