C++ 为什么';t std::共享\u ptr是否使用引用链接?
C++ 为什么';t std::共享\u ptr是否使用引用链接?,c++,c++11,shared-ptr,smart-pointers,reference-counting,C++,C++11,Shared Ptr,Smart Pointers,Reference Counting,std::shared_ptr需要在堆上分配一个包含引用计数的控制块。我还学到了另一种方法,即将所有参考文献保存在一个双链接列表中。它不需要额外的分配或计数器,但引用对象本身更大 是否有一个基准或任何明确的理由表明一种实现优于其他实现?该标准理论上允许使用链接列表,但由于复制共享的\u ptr必须是线程安全的,因此使用链接列表实现这一点会更加困难。该列表需要一个互斥锁(或者是一个无锁列表,这要困难得多)来保护,这样每当一个shared\u ptr被复制或超出范围时,该列表就可以被多个线程安全地修
std::shared_ptr
需要在堆上分配一个包含引用计数的控制块。我还学到了另一种方法,即将所有参考文献保存在一个双链接列表中。它不需要额外的分配或计数器,但引用对象本身更大
是否有一个基准或任何明确的理由表明一种实现优于其他实现?该标准理论上允许使用链接列表,但由于复制
共享的\u ptr
必须是线程安全的,因此使用链接列表实现这一点会更加困难。该列表需要一个互斥锁(或者是一个无锁列表,这要困难得多)来保护,这样每当一个shared\u ptr
被复制或超出范围时,该列表就可以被多个线程安全地修改
使用原子类型进行引用计数和使用原子操作进行引用计数更新要简单得多,而且通常效率更高
编辑:要回答下面的评论,仅仅使用原子指针实现链表是不够的。要从列表中添加或删除节点(对应于增加和减少使用\u count
),您需要以原子方式更新两个指针,以调整添加/删除节点前后节点中的链接std::atomic
允许您以原子方式更新单个指针,但如果您需要以原子方式更新两个这样的对象,则没有帮助。由于这两个指针位于不同的节点中,它们并不相邻,所以即使是四字CAS也无济于事
替代方案是保护整个列表的互斥体(显然不利于争用)或每个列表节点的互斥体,在其中锁定任何更新中涉及的每个节点的互斥体,这将使用更多内存,并且一次最多影响三个节点,即需要锁定三个互斥体。如果use_count()
小于或等于5,则复制/销毁任何一个shared_ptr
与复制/销毁共享同一指针所有权的任何其他实例相竞争。在大多数更新都指向彼此相距较远的非邻居节点的情况下,使用高使用计数可能会减少争用,但在一般情况下可能不会。许多程序使用shared\u ptr
,使用计数为个位数。即使使用计数很高并且在任何节点上都没有争用,您仍然必须锁定三个互斥锁并创建/销毁列表节点(可能需要堆分配)并更新其相邻节点中的指针,因此,原子增量/减量要简单得多,尽管在原子整数上存在争用,但仍可能更快
上次我在委员会上提到,shared\u ptr
不需要使用ref counts,可以使用一个列表,我得到了回复:
鉴于标准现在已经认可多线程,有人真的这么做了吗
和(参考螺纹安全要求):
对于一个引用链接的实现来说,要使它(高效地)工作要困难得多。我甚至不确定这是否可能,尽管可能
您刚刚列出了一个可能优于另一个的明确原因。您确定不能使用引用链接实现共享\u ptr吗?你能给出一个消息来源吗?如果C++不使用标准,因为代码< > SyddypTr>代码>以前没有标准。我不认为标准需要引用计数。它确实在以下内容中提到了这一点:20.7.2.2.6共享的ptr创建[util.smartptr.shared.create]7[注:这些函数通常会分配比sizeof(T)更多的内存,以允许内部簿记结构,如参考计数。-结束注]我认为它允许不同的簿记方式methods@lethal吉他: