我经常看到类似的东西:
NSArray *tmpArr = [[NSArray alloc] initWithObjects:@"Info", nil];
self.userInfo = tmpArr;
[tmpArr release];
而不是:
self.userInfo = [[NSArray alloc] initWithObjects:@"Info", nil];
有谁知道为什么顶级代码示例更受欢迎?内存管理比第二种更准确吗?
答案 0 :(得分:5)
由于数组未被释放,第二个代码段会导致内存泄漏。在大多数情况下,对象类型的属性(在本例中为NSArray
)是retain
或copy
属性,这意味着它们要么增加指定值的引用计数,要么复制整个对象。然后,如果不再需要局部变量,则可以(并且应该)释放局部变量。
第二个代码剪切的非泄漏替代方法是使用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”,这将解决自动泄漏问题),在我看来,首先让一切准备就绪并且然后使其可见是一个好主意。
清洁代码规则:)