访问unordered_set

时间:2016-03-17 08:44:13

标签: c++ stl

请帮助弄清楚将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键。

2 个答案:

答案 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_setunordered_map以及shared_ptr无论如何都有明显的内存开销),但你必须保持冗余信息(对象中idid作为键。

如果您没有多次插入,并且您绝对不需要(平均)常量查找时间和内存开销对您来说非常重要,您可以考虑第三种解决方案(除了使用第三方或自我课程的书面数据结构):即在有序的std::vector<std::shared_ptr<MyClass>>周围写一个薄的包装,或者 - 如果合适 - 更好的std::vector<std::unique_ptr<MyClass>>使用std::upper_bound进行查找。