【问题标题】:Why should I use autorelease in this scenario?为什么我应该在这种情况下使用自动释放?
【发布时间】:2012-12-18 18:54:01
【问题描述】:

我是一个 Objective-c 新手,我只是不明白为什么释放不属于我的对象是个坏主意。

假设我在名为Europe的方法中有这个

//initForStringTheory is a class init method;
Collider *LHC = [Collider initForStringTheory]; 

//Colliders is a NSMutableArray
[Colliders addObject: LHC]  

[LHC release]

我被建议不要在Europe 中释放LHC,因为Europe 不拥有LHC,它只有一个指向它的指针。因此我应该充分利用自动释放池并做

//newCollider is a pointer for the newly created instance in initForStringTheory
return [newCollider autorelease]; 

initForStringTheory。但为什么呢?

Europe 中的指针不也指向实例吗?为什么我不能只在Europe 中释放LHC 而不是在init 方法中返回自动释放newCollider

【问题讨论】:

  • 既然 ARC 可用,那么使用手动内存管理确实没有太多理由。
  • @dandan78 手动内存管理很重要。即使 ARC 为您执行此操作。核心基金会就是这样一个例子。例如,它需要了解 MMM。 ARC 不会为您管理它。
  • @flex Point 承认了。但是,我认为使用它可能不是一个好主意,除非你必须这样做,因为它会引入内存泄漏的可能性。
  • @dandan78 此外,ARC 也并非没有泄漏。有周期是很常见的。无论如何,我真的建议了解这些概念,以更深入地了解 ARC 的工作原理。干杯。

标签: ios memory-management autorelease reference-counting


【解决方案1】:

Stavash 基本上涵盖了,是否释放取决于方法是否返回保留实例。

但是,您并不需要真正了解方法的功能才能正确使用内存管理。 Cocoa MRC 内存管理遵循基于方法名称的方法的规则。根据规则,名称以allocretainnewcopymutableCopy开头的方法返回一个保留的实例,由调用者负责释放。所有其他名称的方法都返回一个非保留实例,调用者不应释放它。

所以,假设(当然,这是一个很大的假设)initForStringTheory 正确地遵循规则,它不应该返回保留实例(这并不意味着它一定是 autoreleased;它可能被某些东西保留否则直接返回给你)。

问题的另一部分是拥有一个名为init...类方法 是非常不合常规的。通常,以init 开头的实例方法是构造函数,它们在创建实例的alloc 的结果上立即运行。那么名为init... 的类方法到底是做什么的呢?此外,按照惯例,init 方法有一个特殊规则,它“消耗”alloc 返回的保留实例,并返回一个(不一定相同)保留实例。但这将如何适用于这种情况,它是在一个类上调用的?它会“消耗”类对象的保留计数(什么都不做),然后返回一个保留的实例吗?没人知道。

总之,这段代码确实需要重写。绝对没有名为init... 的类方法。并确保您编写的所有方法都具有正确遵循规则的内存管理行为,基于它们的名称。

【讨论】:

  • +1 供您解释。好的。我会用initializers 修改术语constructors。但最终的概念是一样的。 ;)
【解决方案2】:

这都是initForStringTheory返回什么的问题——如果这是一个方便的初始化方法,例如[NSArray arrayWithObjects...][NSString stringWithFormat...],它会创建一个你不需要释放的autoreleased实例将其添加到您的收藏后。但是,如果这是一个返回已初始化的非自动释放实例的初始化,则您有责任在将本地实例定义添加到集合后立即在您的方法中释放它。

对象的保留计数在添加时增加 1,因此您不希望它为 2,因为在实例化后您还没有释放/自动释放它(会导致 内存泄漏 因为对象永远不会被释放,即使它不在数组中)。

阅读: http://developer.apple.com/library/mac/#documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html

【讨论】:

  • 所以我不应该在我的场景中释放不属于我的对象的原因是因为将对象的保留计数设为 2 会导致内存泄漏?
  • 不,不释放它的原因是它不是你的释放 - 它是由初始化程序自动释放的,它是你的使用,但你不需要(也不应该)释放它。在这个场景中,我们讨论的是双重发布。
  • 所以如果是初始化返回一个已初始化的非自动释放实例,我可以释放该对象,即使它不属于我(只要我不将保留计数设为是 2)?
  • 它确实属于你——你调用了一个初始化方法,它返回一个现在由你保留的对象,这意味着你有责任释放它。
  • “它创建了一个自动发布的实例”,它不必是自动发布的。它只是没有为您保留
猜你喜欢
  • 2015-12-02
  • 1970-01-01
  • 2018-11-11
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多