【问题标题】:why do you make temporary objects, set them to variables, then release them?为什么要制作临时对象,将它们设置为变量,然后释放它们?
【发布时间】:2011-10-25 13:35:59
【问题描述】:

我经常看到类似的东西:

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

代替:

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

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

【问题讨论】:

标签: objective-c ios


【解决方案1】:

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

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

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

或者简单地说:

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

【讨论】:

    【解决方案2】:

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

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

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

    你也应该看看这个question

    【讨论】:

      【解决方案3】:

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

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

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

      这里。

      QED 第一个原因;-P

      此外,当您首先创建局部变量时,您可以在通过属性公开它们之前构建更复杂的对象。例如,如果您在这里使用 mutable 数组并用一些更复杂的逻辑填充它,立即将其分配给属性并且仅在继续填充它时,您的类的客户可能会访问其内容只准备了一半的属性 - 为零星且难以重现的错误提供了很好的准备。

      因此,即使在您的情况下,使用局部变量并不是绝对必要的(如果您有 autorelease'd 它,我们使用了新的自动参考计算“ARC”,这将解决泄漏问题自动),在我看来,首先准备好一切并然后使其可见总是一个好主意。

      干净的代码规则:)

      【讨论】:

        猜你喜欢
        • 2015-09-24
        • 2016-02-13
        • 1970-01-01
        • 2018-01-13
        • 2021-12-30
        • 2011-11-18
        • 2010-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多