std :: shared_ptr中的最大引用计数是多少?如果你试图超过它会发生什么?

Kno*_*abe 20 c++ reference-counting shared-ptr c++11

如果我们假设std::shared_ptr存储引用计数(我意识到标准不需要,但我不知道任何没有的实现),那个引用计数具有有限的位数,这意味着存在最大数量的支持的引用.这导致了两个问题:

  • 这个最大值是多少?
  • 如果你试图超过它会发生什么(例如,通过复制引用具有最大引用计数的对象的std :: shared_ptr)?请注意,std::shared_ptr声明了复制构造函数noexcept.

该标准是否对这两个问题都有所了解?常见的实现如何,例如gcc,MSVC,Boost?

Jon*_*Jon 19

我们可以从shared_ptr::use_count()函数中获取一些信息.§20.7.2.2.5说:

long use_count() const noexcept;
Run Code Online (Sandbox Code Playgroud)

返回:包含的shared_ptr对象数,*this与之共享所有权*this0何时*this为空.

[注意:use_count()效率不一定.-结束说明]

乍一看,long返回类型似乎回答了第一个问题.然而,这个注释似乎暗示shared_ptr可以自由使用它想要的任何类型的引用计数,包括像引用列表之类的东西.如果是这种情况,那么理论上就没有最大参考计数(尽管肯定存在实际限制).

没有其他参考限制我可以找到的同一对象的引用数量.

值得注意的use_count是,记录的是不投掷和(显然)正确报告计数; 除非实现确实使用long成员进行计数,否则我看不出这两者在理论上是如何保证的.

  • 关于你的上一个陈述,他们不能,而且标准有几个段落让实现摆脱困境.特别是,超出资源限制是未定义的行为,并且如果值不适合,则将不同的整数类型转换为"long"的结果是实现定义的. (3认同)

fat*_*yte 7

我不确定标准的含义,但实际上看看它:

引用计数是最有可能的某种std::size_t变量.此变量可以保存最高-1+2^3232位环境中的值,最高可以保存-1+2^64在64位环境中.

现在想象这个变量要达到这个值会发生什么:你需要2 ^ 32或2 ^ 64个shared_ptr实例.好多啊.事实上,在你达到这个数字之前很久就会耗尽所有内存,因为一个内存shared_ptr大约是8/16字节.

因此,如果refcount变量的大小足够大,则您不太可能达到引用计数的限制.

  • @ fat-lobyte这对于具有平面寻址的机器都是有效的,但我一直在使用48位地址和23位`size_t`的分段机器.(有问题的处理器是一个80386.几乎没有异国情调.)如果机器有平坦的寻址,那么你可以放心地说"不能".如果没有,我甚至不确定你能说"极不可能". (7认同)
  • @MadKeithV你是对的,我编辑了答案. (2认同)

Jam*_*nze 7

标准没有说; 正如你所说,它甚至不需要引用计数.另一方面,标准(或至少在C标准中)中存在(或曾经)超出实施限制的陈述是未定义的行为.所以这几乎肯定是官方的答案.

在实践中,我希望大多数实现将计数保持为a size_t或a ptrdiff_t.在具有平面寻址的机器上,这几乎意味着您无法创建足够的引用来导致溢出.(在这样的机器上,单个对象可以占用所有内存,size_t或者ptrdiff_t与指针具有相同的大小.由于每个引用计数指针都有一个不同的地址,因此永远不会超过指针.)在机器上但是,对于分段架构,溢出是非常可以想象的.

正如乔恩指出的那样,该标准还要求 std::shared_ptr::use_count()退货long.我不知道的理由是什么在这里:要么size_t还是ptrdiff_t会在这里更有意义.但是,如果实现对引用计数使用不同的类型,则可能long会应用转换规则:"如果可以在目标类型(和位字段宽度)中表示,则值不变;否则,值为实现定义".(C标准使这一点更加清晰:"实现定义的值"可以是一个信号.)