【问题标题】:Why does shared_ptr<T>::use_count() return a long instead of an unsigned type?为什么 shared_ptr<T>::use_count() 返回 long 而不是 unsigned 类型?
【发布时间】:2016-07-22 01:52:06
【问题描述】:

shared_ptr 观察者 20.8.2.2.5 C++14 最终草案 (n4296)

   long use_count() const noexcept;

返回:shared_ptr 对象的数量,包括*this,与*this 共享所有权,或者当*this 为空时为0。

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

【问题讨论】:

  • 我想知道如果计数超过LONG_MAX,定义的行为是什么
  • 我猜到那个时候软件已经被其他方面搞砸了

标签: c++ c++14 shared-ptr


【解决方案1】:

根据这个页面

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html

use_count 的返回类型是有符号的,以避免诸如 p.use_count() > -1 评估为假。

参考

John Lakos,大型 C++ 软件设计,第 9.2.2 节,第 637 页,Addison-Wesley,1996 年 7 月,ISBN 0-201-63362-0。

基本上,这看起来像是一个保姆级的决定,专为大一软件开发人员量身定制。

【讨论】:

  • 嗯...看起来像我的第三颗子弹。
  • 一个易于使用的界面,不管他们在想什么?
  • Lakos 的书非常好,可能是对我的 C++ 影响最大的书。一条规则是接口中没有无符号类型。这不是“为大一软件开发人员量身定制的保姆级决策”,而是关于如何扩展软件开发并保持可靠性的深刻建议。
  • 请注意,在此答案N1450 中给出的引号之后紧接着还声明了以下内容:“use_count 的长返回类型并不意味着实现应该始终使用长作为引用计数。在某些情况下,size_t 或其有符号的等价物可能是下面使用的实际类型的更好候选者。”这种返回类型的错误选择应该不足为奇,因为 N1450 还指出:“use_count 被提供为测试和调试辅助工具,而不是用于生产代码。"
  • 那本书的第 9.2.3 节写道:“指南:避免在界面中使用long;”。
【解决方案2】:

原因是这种计数器最适合的类型是常规的signed 整数,即使该计数器永远不会低于 0。

为什么计数器应该是unsigned?鉴于unsigned 对语言的当前真正含义,它不能变成否定的事实根本不是一个有效的借口。

unsigned 对于 C++ 并不意味着“不能为负的整数”。要理解为什么这个定义根本没有意义,请考虑一下

  • 两个unsigned的差是unsigned
  • unsignedsigned 相加为unsigned
  • unsigned 值永远不会大于 -1

如果您认为unsigned 的意思是“非负数”,那么上述任何一个都没有任何意义。

unsigned 用于size_t 是一个错误(参见例如Why is size_t unsigned?),这只是部分* 可以原谅的,因为在16 位时代,一个额外的位被认为值得unsigned 类型具有的错误语义C++ 用于这种用途。

很遗憾,size_t 错误现在无法修复(因为向后兼容),但为什么要在另一个不相关的领域重复同样的错误呢?

请注意,可能犯的大错误只是选择了名称unsigned(考虑到它的真正含义)。如果该类型被命名为(更恰当地)modulo,那么可能更清楚为什么使用modulo int 来表示字符串的大小根本没有任何意义。

名称无关紧要,重要的是语义,unsigned 只是对计数器或大小有错误的语义。

(*) 我个人认为即使在当时也不是一个足够好的理由。如果现在 32767 还不够,那么 65535 很快就不够了。在我看来,仅仅一点点(价值的两倍)对于这种语义弯曲来说是不可接受的。

编辑

我已经发布了video,我在其中更详细地讨论了为什么我认为 size_t 使用和无符号类型是 C++ 中的设计错误。

幻灯片可从http://raksy.dyndns.org/unsigned.pdf下载

【讨论】:

  • 这是咆哮,不是答案。您的声明需要合理的理由并为读者提供任何好处。
  • @6502:首先,Stroustrup 有权发表他的意见,但他错了。其次,无论有什么选择,很久以前就已经做出了决定。标准库大小/计数是无符号的。为什么在地球上这个突然签署确实不清楚。对计数/大小采用无符号类型与获得额外的值范围无关。
  • @6502:第三,无符号类型的本质与支配 C 和 C++ 迭代器语义的开闭范围的本质是一致的。它一直存在于语言的核心中,并且是不可避免的。这不是某人的决定,而是世界如何运作。因此,最初的错误实际上是推进 signed 类型——甚至在 Stroustrup 之前就犯了一个错误。签名类型属于特定于应用程序的域。程序本身是无符号、无符号和无符号的,而且很少有符号。
  • @janm:在很多情况下,单个数组(单个字节)需要占用一半以上的地址空间。甚至更少的情况下,您无法承受使用该大小的多精度整数(例如long)。使用这些案例来改变所有其他用例的规则,谴责未来几代程序员犯愚蠢的错误,因为在我看来这是一个值得商榷的选择。当然,为非负整数提供另一种整数类型(具有正确的语义)可能会很好......但unsigned 不是这样。
  • 在十多年的编程经验之后,我不会使用unsigned类型进行数学/逻辑运算,例如比较。我只在按位运算的情况下使用unsigned。由于从有符号到无符号的自动转换,它使我免于许多陷阱,例如,导致-1 成为一个非常大的值。
猜你喜欢
  • 2020-10-26
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 2021-05-07
  • 2016-11-10
  • 2015-09-22
  • 2014-04-09
相关资源
最近更新 更多