1

我在理解内存管理的一个概念时遇到问题,因为我是目标 C 的新手。例如,假设我有一个类 Bar 和 Foo。

在我调用的主要功能中:

Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo retain];
[foo callMethod];
[foo release];

我知道这是正确的做法。但是为什么我们在从另一个对象中获取它之后必须保留它,这是否意味着返回对象的保留计数为 0 ?所以我们必须重新计算它才能使用它?但如果它的计数为 0,我们怎么知道它仍然存在。我们可以假设,因为它是增加保留计数的下一行,所以对象内存不会被重新分配,但是如果我们有多线程程序怎么办?

4

2 回答 2

3

当一个类方法返回一个对象时,它会返回,autorelease这样你就不必费心了;通常:

- (Foo *)getFoo
{
    return [[_foo retain] autorelease];
}

如果您只foo在调用方法的生命周期内使用它,则不需要它,因为直到下次通过运行循环时retain它才会d ,所以您的代码实际上应该是:autorelease

Foo *foo = [bar getFoo]; //In my bar method I return foo
[foo callMethod];

但是,如果你想foo在调用方法的范围之外保持一段时间,你需要retain它,然后release再过一段时间。

还有一件事; getter 方法名称的约定只是“名称”,所以你的 setter 应该是setFoo,你的 getter 应该是foo. 遵守命名约定是一个好主意,因为它可以让你知道一个方法在 7 个月内做了什么,并且静态分析之类的工具可以理解这些约定。

于 2012-07-09T10:09:32.837 回答
0

该方法getFoo不返回保留计数为 0 的对象。它返回一个具有+0 保留计数的对象,这意味着:

  • 对象的保留计数不为空(否则,该对象将不存在)
  • 并且保留计数没有被方法的调用改变,或者如果它是,它是以一种平衡的方式(与release/ autoreleaseas retain/ alloc/ new/一样多copy)。

因此,对象的生命周期完全取决于它被保留的位置和方式。我们不知道该对象将有效多长时间,因为任何方法调用都可能释放该对象。

例如,让我们考虑以下代码:

id anObject = [anArray objectAtIndex:0];
[anArray removeObjectAtIndex:0];

当我们删除它时,该对象anObject不再被数组保留。因此它可能已被破坏(但也许不是因为它仍在其他地方使用)。

alloc通常,当从方法(除、或)获取对象时copy,我们可以假设:newretain

  • 要么对象被保留然后自动释放,
  • 要么对象被返回它的对象保留。

所以我们知道对象foo是有效的,直到我们从当前方法/函数返回,或者我们调用改变对象状态的方法/函数bar,以先到者为准。在那之后,它可能已经被破坏了。

因此,在您的情况下,您可以安全地省略retain/release对。

然而,除非我们知道我们调用的每个方法的实现,否则很难保证一个对象不会被释放。因此,保留(然后释放)我们获得的每一个对象是更安全的方法,这也是当您启用 ARC(自动引用计数)时编译器将执行的操作。

但这将需要您编写大量retain/release并且您的代码将变得难以阅读、理解和维护。而且,你写的代码越多,得到的 bug 就越多(除非你从不写 bug)。

总之,除非您有理由怀疑它可能会消失,否则您不需要保留对象。

于 2012-07-09T11:04:36.823 回答