共享指针<>是不是需要使用引用计数?

发布于 2024-12-04 09:20:15 字数 262 浏览 3 评论 0 原文

我是否理解新标准,即 不需要使用引用计数shared_ptr?只是很可能是这样实现的?

我可以想象一个以某种方式使用隐藏链表的实现。在N3291“20.7.2.2.5.(8)shared_ptr观察者[util.smartptr.shared.obs]”中,注释说

[ 注意:use_count() 不一定高效。 ——尾注]

这给了我这个想法。

Do I understand the new Std right that shared_ptr is not required to use a reference count? Only that it is likely that it is implemented this way?

I could imagine an implementation that uses a hidden linked-list somehow. In N3291 "20.7.2.2.5.(8) shared_ptr observers [util.smartptr.shared.obs]" The note says

[ Note: use_count() is not necessarily efficient. — end note ]

which gave me that idea.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

很酷又爱笑 2024-12-11 09:20:15

你是对的,规范中没有任何内容要求使用显式的“计数器”,并且存在其他可能性。

例如,建议实施链表实现shared_ptr 的 a>;然而,该提案最终被拒绝,因为它引入了其他领域的成本(大小、复制操作和线程安全)。

You're right, nothing in the spec requires the use of an explicit "counter", and other possibilities exist.

For example, a linked-list implementation was suggested for the implementation of boost's shared_ptr; however, the proposal was ultimately rejected because it introduced costs in other areas (size, copy operations, and thread safety).

过度放纵 2024-12-11 09:20:15

摘要描述

有人说shared_ptr是一个“引用计数器智能指针”。我认为这不是正确的看待方式。

实际上,shared_ptr 都是关于(非独占)所有权的:所有 shared_ptr 都是已初始化的 shared_ptr 的副本带有指针p的是所有者

shared_ptr 跟踪所有者集合,以保证:

  • 当所有者集合非空时,
  • 在以下情况下 不会调用 delete p所有者集合变空,立即调用delete p(或销毁函子D的副本);

当然,要确定所有者集合何时变空,shared_ptr只需要一个计数器。抽象的描述稍微容易思考一些。

可能的实现技术

为了跟踪所有者的数量,计数器不仅是最明显的方法,而且如何使用原子比较和修改来实现线程安全也是相对明显的。

为了跟踪所有所有者,所有者链接列表不仅是显而易见的解决方案,而且还是避免为每组所有者分配任何内存的简单方法。问题在于,要有效使这种方法线程安全并不容易(任何东西都可以通过全局锁来实现线程安全,这违背了并行性的理念)。

在多线程实现的情况下

,一方面,我们有一个小的、固定大小的(除非使用自定义销毁函数)内存分配,这很容易优化,并且有简单的整数原子操作。

另一方面,链表处理成本高昂且复杂;如果需要每个所有者设置互斥体(正如我认为的那样),则内存分配的成本又回来了,此时我们可以用计数器替换互斥体!

关于多种可能的实现

我读过多少次“标准”类可以有多种实现?

谁从未听说过这种幻想:可以将复杂的类实现为极坐标?众所周知,这是愚蠢的。复杂必须使用笛卡尔坐标。如果首选极坐标,则必须创建另一个类。极性复杂类不可能用作通常复杂类的直接替代品。

对于(非标准)字符串类也是如此:字符串类没有理由在内部以 NUL 终止并且不将长度存储为整数,只是为了重复调用 strlen 的乐趣和低效率。

我们现在知道,设计 std::string 来容忍 COW 是一个坏主意,这就是 const 迭代器异常失效语义的原因。

std::vector 现在保证是连续的。

幻想的终结

在某些时候,标准类具有许多显着不同的合理实现的幻想必须被放弃。标准类是原始构建块;它们不仅应该非常高效,而且它们应该具有可预测的效率。

程序员应该能够对基本操作的相对速度做出可移植的假设。如果即使是最简单的加法也会变成一堆超越计算,那么复杂的类对于严肃的数字运算来说是无用的。如果不能保证字符串类通过数据共享进行非常快速的复制,则程序员将不得不最小化字符串复制。

实施者可以自由选择不同的实施技术仅当它不会使常见的廉价操作变得极其昂贵(相比之下)。

对于许多类来说,这意味着只有一种可行的实现策略,有时具有一定程度的自由度(例如 std::deque 中块的大小)。

Abstract description

Some people say that shared_ptr is a "reference counter smart pointer". I don't think it is the right way to look at it.

Actually shared_ptr is all about (non-exclusive) ownership: all the shared_ptr that are copies of a shared_ptr initialised with a pointer p are owners.

shared_ptr keeps track of the set of owners, to guaranty that:

  • while the set of owners is non-empty, delete p is not called
  • when the set of owners becomes empty, delete p (or a copy of D the destruction functor) is called immediately;

Of course, to determine when the set of owners becomes empty, shared_ptr only needs a counter. The abstract description is just slightly easier to think about.

Possible implementations techniques

To keep track of the number of owners, a counter is not only the most obvious approach, it's also relatively obvious how to make thread-safe using atomic compare-and-modify.

To keep track all the owners, a linked list of owner is not only the obvious solution, but also an easy way to avoid the need to allocate any memory for each set of owners. The problem is that it isn't easy to make such approach efficiently thread safe (anything can be made thread safe with a global lock, which is against the very idea of parallelism).

In the case of multi-thread implementation

On the one hand, we have a small, fix-size (unless the custom destruction function is used) memory allocation, that's very easy to optimise, and simple integer atomic operations.

On the other hand, there is costly and complicated linked-list handling; and if a per owners set mutex is needed (as I think it is), the cost of memory allocation is back, at which point we can just replace the mutex with the counter!

About multiple possible implementations

How many times I have read that many implementations are possible for a "standard" class?

Who has never heard this fantasy that the complex class that could be implemented as polar coordinates? This is idiotic, as we all know. complex must use Cartesian coordinates. In case polar coordinates are preferred, another class must be created. There is no way a polar complex class is going to be used as a drop-in replacement for the usual complex class.

Same for a (non-standard) string class: there is no reason for a string class to be internally NUL terminated and not store the length as an integer, just for the fun and inefficiency of repeatedly calling strlen.

We now know that designing std::string to tolerate COW was a bad idea that is the reason for the unusual invalidation semantics of const iterators.

std::vector is now guaranteed to be continuous.

The end of the fantasy

At some point, the fantasy where standard classes have many significantly different reasonable implementations has to be dropped. Standard classes are primitive building blocks; not only they should be very efficient, they should have predictable efficiency.

A programmer should be able to make portable assumptions about the relative speed of basic operations. A complex class is useless for serious number crunching if even the simplest addition turns into a bunch a transcendental computations. If a string class is not guaranteed to have very fast copy via data sharing, the programmer will have to minimize string copies.

An implementer is free to choose a different implementation techniques only when it doesn't make a common cheap operation extremely costly (by comparison).

For many classes, this means that there is exactly one viable implementation strategy, with sometimes a few degrees of liberty (like the size of a block in a std::deque).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文