在将对象添加到集合之前使用自动释放?

Phi*_*ert 5 iphone memory-management objective-c autorelease

我一直在查看StackOverflow上提出的问题,但是在Objective-C中有很多关于内存管理的内容,我找不到我想要的答案.

问题是,在将新创建的对象添加到集合(如NSMutableArray)之前,是否可以(并建议)调用autorelease?或者我应该在添加后明确地发布它.(我知道NSMutableArray会保留对象)

这说明了我的问题:

场景A(自动释放):

- (void) add {
   // array is an instance of NSMutableArray

   MyClass *obj = [[[MyClass alloc] init] autorelease];

   [array addObject:obj];
}
Run Code Online (Sandbox Code Playgroud)

场景B(明确发布):

- (void) add {
   // array is an instance of NSMutableArray

   MyClass *obj = [[MyClass alloc] init];

   [array addObject:obj];

   [obj release];
}
Run Code Online (Sandbox Code Playgroud)

我认为两者都是正确的,但我不确定,我肯定不知道什么是优先的方式.

Objective-C大师可以对此有所了解吗?

joh*_*hne 12

恕我直言,哪种方式是'正确的'是一个偏好的问题.我并不反对主张不使用的响应者autorelease,但我倾向于使用,autorelease除非有绝对令人信服的理由不这样做.我将列出我的理由,你可以决定它们是否适合你的编程风格.

正如查克所指出的,有一个半城市的传说,使用自动释放池有一些开销.这可能不是事实,这来自于使用Shark.app花费无数个小时来挤出代码中的最后一点性能.试图对此进行优化是"过早优化"领域的深层原因.如果且仅当Shark.app为您提供了硬数据,这可能是一个问题,您甚至应该考虑查看它.

正如其他人指出的那样,一个自动释放的对象"会在稍后发布".这意味着他们徘徊在周围,占据记忆,直到"后来的点"滚动.对于"大多数"情况,这是在运行循环休眠直到下一个事件(计时器,用户点击某些内容等)之前的事件处理过程的底部.

但有时,您需要尽快摆脱这些临时物体,而不是以后.例如,您需要处理一个巨大的,多兆字节的文件,或数据库中的数万行.当发生这种情况时,你需要NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];在一个精心挑选的点放置一个,然后[pool release];在底部放置一个.这几乎总是发生在某种"循环批处理"中,因此它通常位于某个关键循环的开始和底部.同样,这应该是基于证据的,而不是基于预感的.Instrument.app的ObjectAlloc是您用来查找这些问题点的方法.

为什么我喜欢的主要原因autoreleaserelease,虽然是,它是写无泄漏的程序更容易.总之,如果你选择去的release路线,你需要保证的是release最终被发送到obj的所有情况.虽然这看起来很简单,但实际上却很难做到.举个例子,举个例子:

   // array is an instance of NSMutableArray
   MyClass *obj = [[MyClass alloc] init];
   [array addObject:obj];
   // Assume a few more lines of work....
   [obj release];
Run Code Online (Sandbox Code Playgroud)

现在想象一下,出于某种原因,某些东西,某个地方,巧妙地违反了你的array可变性假设,可能是使用某种方法处理结果的结果,并且包含处理结果的返回数组被创建为a NSArray.当您发送addObject:到该不可变时NSArray,将抛出异常,您将永远不会发送obj它的release消息.或者objallocd和所需的呼叫之间可能出现问题release,比如你检查一些情况并return()立即错误地因为它让你不知道release以后的呼叫必须发生.

你刚刚泄露了一个物体.并且可能已经签了几天试图找出泄漏的地方和原因.根据经验,您将花费很多时间查看上面的代码,确信它不可能是泄漏的来源,因为您非常清楚地发送obj了一个release.然后,几天之后,你将体验到只能被描述为宗教顿悟的东西,因为你对问题的原因有所启发.

考虑一下autorelease案例:

   // array is an instance of NSMutableArray
   MyClass *obj = [[[MyClass alloc] init] autorelease];
   [array addObject:obj];
   // Assume a few more lines of work....
Run Code Online (Sandbox Code Playgroud)

现在,它不再重要,因为obj即使在非常不寻常或特殊的角落情况下,它几乎不可能意外泄漏.


Dav*_*ong 7

两者都是正确的,并且会像你期望的那样工作.

我个人更喜欢使用后一种方法,但仅仅因为我喜欢明确何时释放对象.通过自动释放对象,我们所做的只是说"这个对象将在未来的某个任意点被释放." 这意味着你可以将自动释放的对象放入数组中,销毁数组,并且对象可能(可能)仍然存在.

使用后一种方法,对象将立即被阵列销毁(假设没有其他任何东西出现并在此期间保留它).如果我在一个内存受限的环境(比如iPhone)中我需要注意我正在使用多少内存,我将使用后一种方法,因此我没有那么多的对象挥之不去一个NSAutoreleasePool.如果内存使用对你来说不是一个大问题(通常也不适合我),那么任何一种方法都是完全可以接受的.

  • 如果您希望您的代码绝对安全,强烈建议您使用自动释放:请参阅http://stackoverflow.com/questions/1147785/use-autorelease-before-adding-objects-to-a-collection/1149040#1149040 (2认同)