基础知识:不使用retainCount 的官方理由是什么?
自动释放管理是最明显的——您无法确定有多少由 代表的引用retainCount
在本地或外部(在辅助线程上,或在另一个线程的本地池中)自动释放池中。
此外,有些人在泄漏、更高级别的引用计数以及自动释放池如何在基本级别上工作时遇到问题。他们将编写一个程序,而不(太多)考虑正确的引用计数,或者没有正确学习引用计数。这使得他们的程序很难调试、测试和改进——这也是一个非常耗时的修正。
不鼓励使用它(在客户端级别)的原因有两个:
1) 由于很多原因,该值可能会有所不同。单单线程就是永远不要相信它的理由。
2)您仍然必须实施正确的引用计数。retainCount
永远不会使您免于不平衡的引用计数。
是否有任何可能有用的情况?
如果您编写自己的分配器或引用计数方案,或者如果您的对象位于一个线程上并且您可以访问它可能存在的任何和所有自动释放池,那么您实际上可以以有意义的方式使用它。这也意味着您不会与任何外部 API 共享它。模拟这一点的简单方法是创建一个具有一个线程、零个自动释放池的程序,并以“正常”方式进行引用计数。除了“学术”原因之外,您不太可能需要解决这个问题/编写这个程序。
作为调试帮助:您可以使用它来验证保留计数是否异常高。如果您采用这种方法,请注意实现差异(本文中引用了一些),并且不要依赖它。甚至不要将测试提交到您的 SCM 存储库。
在极为罕见的情况下,这可能是一种有用的诊断方法。它可用于检测:
过度保留:如果您的程序可以访问分配,则保留计数正不平衡的分配不会显示为泄漏。
一个被许多其他对象引用的对象:这个问题的一个例子是在多线程上下文中运行的(可变)共享资源或集合 - 频繁访问或更改此资源/集合可能会在程序执行中引入重大瓶颈。
自动释放级别:自动释放、自动释放池和保留/自动释放周期都需要成本。如果您需要最小化或减少内存使用和/或增长,您可以使用这种方法来检测过多的案例。
来自 Bavarious 的评论(下):高值也可能表示分配无效(dealloc'd 实例)。这完全是一个实现细节,同样不能在生产代码中使用。启用僵尸时,向此分配发送消息会导致错误。
应该怎么做?
如果你不负责返回内存self
(也就是说,你没有写分配器),别管它——它没用。
您必须学习正确的引用计数。
为了更好地理解释放和自动释放的使用,设置一些断点并了解它们是如何使用的,在什么情况下等等。你仍然需要学习正确使用引用计数,但这可以帮助你理解为什么它是无用的.
更简单:使用 Instruments 跟踪分配和引用计数,然后分析活动程序中多个对象的引用计数和调用堆栈。
历史/解释:如果不打算使用,为什么 Apple 会在 NSObject 协议中提供此方法?Apple 的代码是否出于某种目的依赖于 retainCount?如果是这样,为什么不把它藏在某个地方?
我们可以假设它是公开的,主要有两个原因:
1)在托管环境中正确的引用计数。分配器可以使用retainCount
——真的。这是一个非常简单的概念。当被调用时,可能会调用 ref 计数器(除非被覆盖),如果为 0(调用 dealloc 之后)-[NSObject release]
,则可以释放对象。retainCount
在分配器级别这一切都很好。分配器和区域(很大程度上)是抽象的,所以......这使得结果对普通客户毫无意义。retainCount
有关为什么在客户端级别不能等于 0、对象解除分配、解除分配序列等的详细信息,请参阅 bbum 的评论(如下) 。
2) 使其对想要自定义行为的子类可用,并且因为其他引用计数方法是公共的。在少数情况下它可能很方便,但它通常用于错误的原因(例如不朽的单例)。如果您需要自己的引用计数方案,那么这个系列可能值得覆盖。
为了更深入地理解:对象的保留计数可能与用户代码中假设的不同的原因是什么?您能否给出框架代码可能使用的标准过程的任何示例***,这些示例会导致这种差异?是否存在任何已知情况,其中保留计数总是与新用户的预期不同?
同样,自定义引用计数方案和不朽对象。NSCFString
文字属于后一类:
NSLog(@"%qu", [@"MyString" retainCount]);
// Logs: 1152921504606846975
关于retainCount,您认为还有什么值得一提的吗?
它作为调试辅助是没有用的。学习使用泄漏和僵尸分析,并经常使用它们——即使在你掌握了引用计数之后。
更新: bbum 最近发了一篇文章,题为retainCount is useless。这篇文章详细讨论了为什么-retainCount
在绝大多数情况下没有用。