将对象添加到集合之前,使用自动释放?(Use autorelease before adding o

2019-06-26 07:05发布

我一直在寻找通过询问StackOverflow上的问题,但有这么多有关Objective-C的内存管理,我无法找到我一直在寻找的答案。

现在的问题是,如果它是确定(和recommnded)将新创建的对象的集合(比如NSMutableArray的)之前调用自动释放? 或者我应该将它添加后明确地释放它。 (我知道的NSMutableArray预订购保留的对象)

这说明我的问题:

方案A(自动释放):

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

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

   [array addObject:obj];
}

方案B(显式发布):

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

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

   [array addObject:obj];

   [obj release];
}

我认为都是正确的,但我不知道,我肯定不知道的方式参访什么。

Objective-C的大师能提供一些线索对此有何看法?

Answer 1:

两者都是正确的,因为你是他们期待将工作。

我个人更喜欢使用后一种方法,但只是因为我喜欢明确的关于对象时得到释放。 通过自动释放的对象,所有我们正在做的是说“这个对象将在未来的某个任意点获得释放。” 这意味着你可以把自动释放对象放入数组,破坏了数组和对象可能(可能)仍然存在。

对于后者的方法,对象会得到立即与阵列(提供没有其他已出现并保留其在此期间)被破坏。 如果我在一个内存受限的环境中(比如,iPhone的),我需要小心我使用多少内存,我会用后一种方法只是让我没有那么多的物体在缠绵一个NSAutoreleasePool地方。 如果内存使用是不是你一个大问题(它通常是不适合我,要么),那么无论方法完全可以接受的。



Answer 2:

恕我直言,这方法是“正确”是偏好的问题。 我不同意谁主张不使用应答不同意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];

现在想象一下,由于某种原因,东西,地方,巧妙地侵犯了您的假设array是可变的,也许会使用一些方法来处理结果的结果,以及含有处理结果返回阵列作为创建NSArray 。 当您发送addObject:以不可变NSArray ,一个会抛出异常,你将永远不会发送objrelease的消息。 或者,也许不顺心的事时,地方之间objalloc d和所需的呼叫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....

现在,它不再是问题,会发生什么,因为它几乎是不可能泄露obj意外,即使在极不寻常的或特殊的角落案件。



Answer 3:

他们都是正确的,但B可以首选,因为它没有任何开销。 自动释放将导致自动释放池,负责的对象。 这有它,当然,得到所涉及的对象的数量乘以一个非常小的开销。

因此,与一个对象A和B都或多或少相同,但绝对不会在方案中使用一个具有大量的对象添加到阵列。

在不同的情况自动释放可能会延迟,并在线程结束积累许多对象的释放。 这可能是次优的。 要小心,反正自动释放发生了很多没有明确的干预。 例如,许多干将都以这种方式实现:

return [[myObject retain] autorelease];

所以每当你打电话,吸气,你的对象添加到自动释放池。



Answer 4:

您可以将autorelease的任何一点消息,因为它没有采取行动,直到应用程序的消息循环重复(即,直到所有的方法都完成了响应用户输入执行)。

http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text



Answer 5:

你有alloc “编的对象,那么你的工作在某些时候将其释放。 这两个代码段的工作仅仅是相同的,正确的方法,用autorelease方式作为potentionally慢对口。

个人来说,我更喜欢autorelease方式,因为它只是更容易输入,几乎从来都是一个瓶颈。



Answer 6:

他们都OK。 有些人会告诉你,以避免因“开销”或一些这样的东西自动释放,但事实是,几乎没有任何开销。 来吧,基准,并设法找到“开销”。 你会避免它的唯一原因是在像iPhone上的内存匮乏的局面。 在OS X,你实际上是无限的内存,因此它不会产生太大的差别。 只需使用取其您最方便的。



Answer 7:

我更喜欢A(自动释放)为了简洁和“安全”,因为强尼调用它。 它简化了我的代码,我从来没有遇到与它的问题。

也就是说,直到今天:我有一个问题,它添加到阵列之前自动释放块。 看到我的计算器问题: [myArray的ADDOBJECT:[objcBlock复制]自动释放]上dealloc'ing阵列崩溃 (更新:原来,问题是在我的代码的其他地方,不过,有与自动释放行为细微的差别... )



文章来源: Use autorelease before adding objects to a collection?