NSMutableArray -init 与 +arrayWithCapacity: 的区别

10
我有两个函数,我应该使用哪一个?请解释它们的区别。
A:
- (NSMutableArray *)FunctionA:(int)count {

    NSMutableArray *a = [[NSMutableArray alloc] init];

 for (int i = 0; i < count; i++) {
  [a addObject:[NSNumber numberWithInt:0] ];
    }

    return [a autorelease];
}

B:

-(NSMutableArray *)FunctionB:(int)count {

 NSMutableArray *b = [NSMutableArray arrayWithCapacity:count];

 for (int i=0;i<count; i++){  
  [b addObject:[NSNumber numberWithInt:0] ];  
 }

 return b;  //  or [b autorelease] ?
}
4个回答

28
第一种创建可变数组时没有指定容量,这会导致在添加元素时必须扩展数组。在内部进行了“分块”优化,但仍需要增长数组并分配更多空间以添加元素。
第二种方法给数组一个提示(你可能需要“这么多”空间)以避免在添加已知数量的对象时增加数组的开销。当然,如果需要,它仍会变得更大(就像你没有指定容量一样)。如果您已经提前知道计数,请使用此方法。对于较大的计数速度更快。
然而,这样做有一个缺点,如果您在优化之前没有进行测量:如果您创建具有非常高容量的可变数组但不总是使用该容量,则会因为分配所有那些空间而遭受惩罚。
另外,您不会自动释放B(如您所注释)因为您没有使用init创建可变数组-您使用了自身完成初始化的便利方法,这意味着您不需要负责释放它。正如我在回答您问题的另一篇答案的评论中提到的,您还可以使用以下代码创建数组:
[[NSMutableArray alloc] initWithCapacity:capacity];
当准备好时释放它。这比使用自动释放池更能控制内存使用,这在iPhone平台上是一个重要考虑因素。
但请记住:先测量,然后如有必要再进行优化。

1

可变对象仍然需要分配空间,因此将为10个对象分配默认数量。如果添加第11个对象,则可变数组将不得不分配新的内存,将项目复制到新的内存中,并释放旧的内存。

通常这很快,你甚至都不会注意到,但它可能会减慢速度。使用大小创建可变数组最初创建指定大小的数组,因此希望发生较少的调整大小。


1
在第一个示例中,您必须管理数组的内存,因为您使用+alloc-init创建它(这就是为什么您需要向其发送-autorelease)。
在第二个示例中,您不必管理数组的内存,因为它已经被自动释放了(因为您使用方便的方法创建它)。此外,由于您事先指定了数组的所需大小,因此它可能更有效率。
如果您想返回一个自动释放的数组,则第二个选项可能更可取,因为+arrayWithCapacity:将返回一个已经自动释放的数组。而且,由于返回给您的数组已经被自动释放,因此您不必自己发送-autorelease
如果您对内存管理有任何更多的疑虑,那么阅读苹果公司的内存管理指南是必须的。

0

我会使用B:

我认为它的优点有:

  • 随着数组变大,它不需要调整大小
  • arrayWithCapacity: 会自动释放,这样可以提高代码的可读性

希望这能帮到你。


虽然在某些情况下,您可能希望更多地控制内存使用量,但您仍然可以使用[[NSMutableArray alloc] initWithCapacity:c]创建它,然后在准备好时释放它。 - Joshua Nozzi
只是为了澄清我的先前评论 - 这是在 iPhone 上需要考虑的重要问题,我提到了“iphone”标签。 :-) - Joshua Nozzi
绝对正确。我没有注意到标签,如果这是一个大数组,那可能是一个严重考虑的问题。然而,内存管理指南有其存在的合理性。一致的使用非常重要,只有在你确切知道为什么,并且没有更好的方式时才应该打破它。 - Bryan McLemore
我不确定我理解为什么这是一个“然而”。:-D无论您是否使用自动释放池或提示数组的容量,都不意味着或必须违反内存管理规则。您能澄清一下您的意思吗? - Joshua Nozzi
虽然我肯定会尊重您的经验,但我的意思更多是通过创建对象并在没有自动释放的情况下返回它来破坏它们。如果您从函数中获取了对象,然后完全忘记释放它,这是一个相当常见的错误,您可能会导致严重的内存泄漏问题。实际上,如果像“a”这样的函数没有在结尾处自动释放,那么就会出现潜在的内存泄漏clang警告。很抱歉没能早点回复,我在吃午餐。 - Bryan McLemore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接