Mutable类是否“更重?”

时间:2012-02-07 17:37:30

标签: objective-c ios nsmutablearray mutable

在一些直观的(也许是错误的)性能概念上,我总是在存储它之前获得copy可变实例。因此,如果属性需要NSArray,我会使用我正在使用的可变数组并将其存储为self.array = mutableArray.copy(尽管该属性指定为strongretain)。

突然间,这对我来说似乎很傻,但是呢?做可变实例 - 执行完全相同的任务 - 执行相同的操作吗?

注意:可变实例超出了范围,并且(感谢ARC)在此之后立即释放,因此不必担心一旦将其分配给属性就会发生变异。

3 个答案:

答案 0 :(得分:3)

部分回答:NSArray size and mutability

NSMutableArray明显比NSArray更慢或更大(内存方面)。它基本上只是一个NSArray,当它变得像一个更大的数组一样时会重新分配它,并在你向它添加项目时继续这样做。

在将可变数组分配给类中的值时,将可变数组复制为不可变数组的原因是,您可以保证它们的值不会更改。如果在类中存储可变数组,则其他代码可以在类之外更改其值,而无需调用任何方法。由于您的类中存在内部不稳定错误,因此您很容易崩溃。

例如,假设在设置数组时,您将数组的长度缓存为类中的int属性。如果数组是不可变的,那就好了,但是如果它是可变的,那么其他人可以更改数组,而你的缓存值现在会出错,但你无法知道。

但是,没有必要手动复制。如果将数组属性声明为:

@property (nonatomic, copy) NSArray *foo;

然后,每当您将一个数组分配给object.foo时,它将自动被复制。您不需要自己复制它。对于具有可变变体的任何类型,最好使用属性类型的副本而不是强/保留,如下所示:

@property (nonatomic, copy) NSArray *foo;
@property (nonatomic, copy) NSString *foo;
@property (nonatomic, copy) NSDictionary *foo;
@property (nonatomic, copy) NSData *foo;
etc...

但是要注意不要将它用于可变属性,否则它会使一个不可变的副本存储在一个认为它是可变的属性中,如果你试图改变它就会导致崩溃。合成的复制属性不够智能,无法自动使用mutableCopy。

@property (nonatomic, copy) NSMutableArray *foo; //don't do this

答案 1 :(得分:3)

NSArrayNSMutableArray都是(据我所知)在CFArray之上实现的,它只是有一个标志,指明它是否可变。需要可变数组的CFArray函数在开头有一个断言,检查该标志:

void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
    // snip...
    CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);

可变和不可变CFArray除了传递或失败此断言之外是相同的,因此NSArrayNSMutableArray应该是,性能或其他方式。

答案 2 :(得分:2)

为了清楚起见,您要问的是,如果NSArray和NSMutableArray都接受了一系列非变异测试方法,那么NSArray的表现是否会明显加快?我指定非mutataing,因为它看起来像是在将可变数组复制到不可变数组,并认为不可变数组将比可变数组更快地执行其非变异方法。无论如何,答案是否定的。 (但不要接受我的话;简介)。

即使NSMutableArray超越了一些非变异方法(我们无论如何都不知道),你也不用担心它。与操作的整体计算复杂性相比,添加几个CPU周期是微不足道的。只要NSMutableArray没有设法将O(n)查找操作转换为O(n 2 )操作,您99%的时间都可以正常工作。 (这些复杂性仅仅是虚构的例子)。

虽然有充分合理的理由可以将可变数组复制到不可变数组中(正如@NickLockwood所指出的那样),但性能不应该是其中之一。毕竟,过早优化是非常糟糕的。