修改(unordered_)集合中的shared_ptr是否安全?

时间:2014-07-31 11:36:43

标签: c++ stl set shared-ptr unordered-set

存储在setunordered_set中的元素是不可变的。如果更改存储在set中的元素,则可能导致该集合不再正常工作。 但是,在将shared_ptr存储在集合中时,这是否包含指向对象?

set而言,它使用less()来比较两个对象。如果指向的对象发生更改或引用计数发生更改,则结果不应更改。所以我理解,拥有一组shared_ptr并修改指向的对象是完全安全的。

但是,由于unordered_set使用hash()来计算其元素的哈希值,这相当于在hash()的指向对象上调用shared_ptr,因此修改指向的对象会让我们陷入困境。

这是对的吗?

3 个答案:

答案 0 :(得分:1)

shared_ptr<T>的哈希函数不依赖于它所指向的实例的状态。因此,您可以安全地修改状态而不会使容器失效。

答案 1 :(得分:1)

对于指针值,智能指针的

hash()等效于hash(),但指针值的hash()仅取决于指针,而不取决于指针。因此,您可以安全地修改容器中的对象 - 哈希函数结果将不会更改。

答案 2 :(得分:-1)

STL集使用红黑树作为实现 - (其原因是具有统一的插入时间;没有像哈希映射那样的线性最坏情况);如果更改密钥,则树不再平衡;该实现使用运算符&lt;和operator ==,而不是哈希。

unordered set使用桶哈希表作为实现;这里使用哈希;更改密钥意味着该条目将不再属于哈希表的同一个桶。

shared_ptr&#39运营商&lt;和operator ==比较智能指针所持有的指针值,仍然改变键不会维持实现这个容器的数据结构的排序关系。

共享ptr的哈希值将只是包装指针的数值

  template<typename _Tp, _Lock_policy _Lp>
    struct hash<__shared_ptr<_Tp, _Lp>>
    : public std::unary_function<__shared_ptr<_Tp, _Lp>, size_t>
    {
      size_t
      operator()(const __shared_ptr<_Tp, _Lp>& __s) const
      { return std::hash<_Tp*>()(__s.get()); }
    };

template<typename _Tp>
  struct hash<_Tp*> : public __hash_base<size_t, _Tp*>
  {
    size_t
    operator()(_Tp* __p) const
    { return reinterpret_cast<size_t>(__p); }
  };

关于gcc stl:

c++/<version>/map inculudes c++/<version>/bits/stl_set.h 

c++/<version>/bits/stl_set.h

  template<typename _Key, typename _Compare = std::less<_Key>,
           typename _Alloc = std::allocator<_Key> >
    class set
    {
   typedef _Rb_tree<key_type, value_type, _Identity<value_type>,
                    key_compare, _Key_alloc_type> _Rep_type;
   _Rep_type _M_t;  // Red-black tree representing set.

c++/<version>/bits/tree.h
    <here red black tre _Rb_tree class is implemented>

 c++/<version>/unordered_set includs c++/<version>/bits/unordered_set.h this one uses hashtable in c++/<version>/bits/hashtable.h