请帮助弄清楚将unordered_set与自定义结构一起使用的逻辑。 考虑我有以下课程
struct MyClass {
int id;
// other members
};
与shared_ptr一起使用
using CPtr = std::shared_ptr<MyClass>;
由于密钥的快速访问,我应该使用带有自定义哈希的unordered_set和MyClass :: id成员作为密钥):
template <class T> struct CHash;
template<> struct CHash<CPtr>
{
std::size_t operator() (const CPtr& c) const
{
return std::hash<decltype(c->id)> {} (c->id);
}
};
using std::unordered_set<CPtr, CHash>;
现在,unordered_set似乎仍然是一个合适的容器。但是,假设set的标准find()函数是const,以确保不会更改密钥。我打算改变对象,保证键不变。所以,问题是:
1)如何实现通过int键保存更改元素的可能性来轻松访问set元素,如
auto element = my_set.find(5);
element->b = 3.3;
可以添加转换构造函数并使用类似
的内容auto element = my_set.find(MyClass (5));
但它并没有解决constness的问题,如果这个类很大,该怎么办。
2)我真的错了吗?我应该使用另一个容器吗?例如unordered_map,它将为每个消耗更多内存的条目存储一个以上的int键。
答案 0 :(得分:1)
我认为你使用unordered_set是错误的,因为unordered_set的定义非常明确:
键是不可变的,因此,unordered_set中的元素不能在容器中修改一次 - 但是可以插入和删除它们。
您可以在网站上看到它的定义:
http://www.cplusplus.com/reference/unordered_set/unordered_set/
希望它对你有所帮助。谢谢。
答案 1 :(得分:1)
指针不会将其常量投影到它指向的对象。意思是,如果你有一个std::shared_ptr
的常量引用(如在一个集合中),你仍然可以通过这个指针修改对象。这是否是你应该做的事情是一个不同的问题,它并没有解决你的查找问题。
当然,如果你想通过一个键来查找一个值,那么这就是std::unordered_map
的设计目的,所以我在那里仔细看看。我用这种方法看到的主要问题不是内存开销(unordered_set
和unordered_map
以及shared_ptr
无论如何都有明显的内存开销),但你必须保持冗余信息(对象中id
和id
作为键。
如果您没有多次插入,并且您绝对不需要(平均)常量查找时间和内存开销对您来说非常重要,您可以考虑第三种解决方案(除了使用第三方或自我课程的书面数据结构):即在有序的std::vector<std::shared_ptr<MyClass>>
周围写一个薄的包装,或者 - 如果合适 - 更好的std::vector<std::unique_ptr<MyClass>>
使用std::upper_bound
进行查找。