返回一个自动释放的对象是一种抽象形式——对开发人员来说是一种方便,因此他/她不必考虑返回对象的引用计数——从而导致特定类别中的错误更少(尽管你也可以说自动释放池引入了新类别的错误或复杂性)。它可以真正简化客户端代码,虽然是的,但可能会有性能损失。当不需要进行引用操作时,它也可以用作抽象优化 - 考虑何时对象包含返回的实例并且不需要进行保留或复制。虽然链接语句可能会被过度使用,但这种做法对于链接语句也很方便。
此外,确定引用计数错误的静态分析器对于其中一些库和程序来说是相对较新的。自动释放池比 ARC 和 objc 对象引用计数的静态分析早了很多年——现在使用这些工具确保您的引用计数是正确的要简单得多。他们能够检测到许多错误。
当然,使用 ARC,如果您喜欢返回自动释放对象的简单性,那么很多情况都会发生变化——使用 ARC,您可以返回更少的自动释放对象,而不会引入抽象的自动释放池错误。
使用统一所有权语义还可以简化程序。如果一个抽象选择器或选择器集合总是使用相同的语义返回,那么它确实可以简化一些通用形式。例如——如果传递给的一组选择器performSelector:
具有不同的所有权返回语义,那么它会增加很多复杂性。因此,统一的回报所有权可以真正简化一些更“通用”的实现。
性能:引用计数操作(保留/释放)可能相当重要——尤其是当您习惯于在较低级别工作时。但是,当前的自动释放池实现非常快。它们最近已更新,并且比以前更快。编译器和运行时使用几个特殊的快捷方式来降低这些成本。减少自动释放池的大小也是一个好主意——尤其是在移动设备上。创建自动释放池非常快。在实践中,您可能会看到自动释放操作本身增加了零到几个百分点(即它消耗的时间比objc_msgSend
+变体)。一些测试甚至跑得更快。这不是许多人会从中受益匪浅的优化。在典型情况下,它不会被认为是唾手可得的成果,而且在实际程序中测量这种变化的影响和局部性实际上是相对困难的——基于我在 bbum 提到下面的变化后所做的一些测试。因此测试范围有限,但在 MRC 和 ARC 中似乎更好/更快。
因此,如果您正在执行自己的引用计数操作,这很大程度上取决于您想要承担的责任级别。对于大多数人来说,它不应该真正改变他们的写作方式。我认为本地化内存问题、更具确定性的对象破坏和更可预测的堆大小是如果您在现代系统上运行,人们可能倾向于返回“拥有”(+1)引用计数的主要原因。即便如此,运行时和编译器在许多情况下都会为您减少这种情况(请参阅 bbum 的回答 +1)。尽管自动释放池的速度差不多,但我现在不打算比现在更多地使用它们——所以仍然有合理的理由尽量减少使用它们,但理由正在减少。