在(无序)集合中修改shared_ptr是否安全?

4

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

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

但是,由于unordered_set使用hash()来计算其元素的哈希值,这相当于在shared_ptr的指向对象上调用hash(),因此修改指向的对象会导致问题。

这正确吗?


2
据我所知,哈希和运算符都作用于指针而非指向的对象... 因此修改指向的对象应该没有影响,我认为在集合或映射中存储似乎毫无意义,我认为使用向量也足够了。 - Nim
哦,是的,我在检查hash<shared_ptr<T>>的实现时犯了错误。谢谢你指出来! - sigy
除非您分别专门处理运算符或哈希函数。 - leemes
我认为这个问题闻起来像是对共享智能指针容器的错误决定。 - user1095108
@user1095108 你为什么这么认为呢?这完全取决于使用情况。如果顺序不重要,我会发现一组共享指针很方便。(但是,unordered_setset更有意义) - leemes
显示剩余2条评论
3个回答

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


谢谢Rex,我不知道''s的存在。 - Brandon Kohn
1
如果您使用std::less<shared_ptr<T>>是用于什么?用于比较函数吗?无序集合不使用关系比较,而是使用哈希函数。在发生冲突的情况下,需要进行相等比较,这是std::less<shared_ptr<T>>无法实现的。 - Benjamin Lindley
1
使用重音符号来包围内联代码,而不是单引号。在左上角,ESC键下方,未按Shift键时,在我所见过的键盘上至少是这样。 - Benjamin Lindley

1
智能指针的hash()等同于指针值的hash(),但指针值的hash()仅取决于指针,而不取决于指向的对象。因此,在容器中修改对象是安全的——哈希函数结果不会改变。

哦,是的,我在检查hash<shared_ptr<T>>的实现时犯了一个错误。感谢您指出来! - sigy

-1

STL set使用红黑树作为实现方式 -(这样做的原因是为了具有统一的插入时间;没有像哈希映射那样的线性最坏情况);如果更改键,则树将不再平衡;该实现使用operator<和operator==,而不是哈希。

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

shared_ptr的operator<和operator==比较智能指针持有的指针值,但更改键将无法维护实现此“容器”的数据结构的排序关系。

共享指针的哈希值将仅是包装指针的数值。

  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

“[set]使用operator<和operator==” - 实际上只是<,当既不是a < b也不是b < a时,它会推断相等。更一般地说,我认为问题是关于改变指向的数据是否构成了对于set<unordered_sethash的键的更改.... - Tony Delroy
谢谢,但这已经在我的问题中更或多少地说明了 ;) - sigy
shared_ptr的operator<和operator==比较的是智能指针所持有的指针值,然而更改键将不能维护实现此“容器”的数据结构的排序关系。 - MichaelMoser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接