为什么要制作临时对象,将它们设置为变量,然后释放它们?

时间:2011-10-25 13:36:00

标签: objective-c ios

我经常看到类似的东西:

NSArray *tmpArr = [[NSArray alloc] initWithObjects:@"Info", nil];
self.userInfo = tmpArr;
[tmpArr release];

而不是:

self.userInfo = [[NSArray alloc] initWithObjects:@"Info", nil];

有谁知道为什么顶级代码示例更受欢迎?内存管理比第二种更准确吗?

3 个答案:

答案 0 :(得分:5)

由于数组未被释放,第二个代码段会导致内存泄漏。在大多数情况下,对象类型的属性(在本例中为NSArray)是retaincopy属性,这意味着它们要么增加指定值的引用计数,要么复制整个对象。然后,如果不再需要局部变量,则可以(并且应该)释放局部变量。

第二个代码剪切的非泄漏替代方法是使用autorelease

self.userInfo = [[[NSArray alloc] initWithObjects:@"Info", nil] autorelease];

或简单地说:

self.userInfo = [NSArray arrayWithObjects:@"Info", nil];

答案 1 :(得分:2)

假设属性userInfo标记为retain,第二种形式将泄漏内存。 [[NSArray alloc] initWithObjects]将创建一个引用计数为1的数组。将其分配给retain属性会将引用计数增加到2,并且它永远不会回归到零并被释放。它可以通过使用您列出的第一个表单或通过以下方式修复:

self.userInfo = [[[NSArray alloc] initWithObjects:@"Info", nil] autorelease];

这样自动释放将在运行循环的下一次迭代中将引用计数减少到1。从那时起,当userInfo被清除时,引用计数将下降到零并且数组将被销毁。

您还应该看看这个question

答案 2 :(得分:2)

除了可能存在的任何其他原因外,它还使代码更具可读性并有助于防止错误。

您的两个示例并不等效,因为您忘记在第二个示例中释放新的alloc/init'ed数组。你需要

self.userInfo = [[[NSArray alloc] initWithObjects:@"Info", nil] autorelease];

这里。

QED第一个理由;-P

此外,当您首先创建局部变量时,可以在通过属性公布它们之前构建更复杂的对象。例如,如果你在这里使用可变数组并用一些更复杂的逻辑填充它,立即将它分配给属性,只有在填写它时,你的类的客户端才可以访问该物业的内容只有一半准备好 - 一个很好的规定,零星和难以重现的错误。

所以,即使在你的情况下,使用局部变量也不是绝对必要的(如果你有autorelease那么我们使用了新的自动参考Couting“ARC”,这将解决自动泄漏问题),在我看来,首先让一切准备就绪并且然后使其可见是一个好主意。

清洁代码规则:)