我有两个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
答案 0 :(得分:0)
免责声明:我是OP,并且是C ++的新手。我的代码现在可以按预期的方式编译和运行,尽管我确实相信以下所有信息都是正确的,但是请留下评论以通知我任何错误。
对于那些感兴趣的人,我最终在A类中创建了两个公共函子(内部,因为我需要访问私有成员(也可以使用friend
),并在声明中使用它们std::unordered_set
。对于类型,我使用了A *。更好的解决方案可能是使用智能指针,但是我对此并不陌生,因此我尚未对其进行详细研究。
关于std::unordered_set
,我了解了以下内容:
std::shared_ptr
,std::unique_ptr
,...),使用std::reference_wrapper<T>
,或使用类型本身。请注意,不允许将A&
之类的引用作为std::unordered_set
的value_type,因此不允许将其作为包装器。operator ==
。在第5点中,提出了解决方案。operator ==
用作默认的“等号”。在这里只需要定义哈希器即可。但是,您应该警惕std::unordered_set::insert()
会创建插入的元素的副本,因此,如果其中包含静态分配的成员数据,则应确保在开始复制该类型的实例时,程序仍能正常运行。我认为这是最不冗长的解决方案,也是我发现最多示例的解决方案。 (使用std::unordered_set::emplace()
可能是解决整个复制问题的一种方法,但我还没有弄清楚。)std::hash<T>
和/或std::equal_to<T>
,或通过为此创建函子。有关如何执行此操作的更多信息here。这些基本上可以做同样的事情,因此可以互换。如第4点所述,当您存储直接类型时,还有另外一种选择,您也可以使用operator ==
,然后在声明{{1}时无需指定任何'等号' }。