最近我经常使用数组,我想知道..这两行之间有什么区别。
NSArray *array = [NSArray arrayWithArray:someArray];
和
NSArray *array = [someArray copy];
哪个更快?如果我们有NSMutableArray
andmutableCopy
怎么办?
最近我经常使用数组,我想知道..这两行之间有什么区别。
NSArray *array = [NSArray arrayWithArray:someArray];
和
NSArray *array = [someArray copy];
哪个更快?如果我们有NSMutableArray
andmutableCopy
怎么办?
哪个更快?
别担心。过早的优化。
主要区别:第一种方法会产生一个自动释放的“副本”,您不拥有也不必释放,而您确实拥有在第二行创建的对象。顺便说一句,这两个数组都是不可变的。
除了其他答案,还请注意,当someArray
为 nil 时,第一行将array
指向一个空数组,第二行将使其指向 nil。这可能是一个重要的区别,尤其是在可变数组中。
两者的区别在于后者会被保留。前者将自动发布。
两个版本都制作了数组的浅拷贝。
NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];
应该给您一个编译器警告,因为您将尝试将 a 分配NSArray
给 a NSMutableArray
。
采用。
NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];
哪个更快?别担心,它们都比您将要做的其他事情快得多。如果您真的在乎,请与 Instruments 联系。
主要区别在于它-copy
知道如何复制自己(可以更有效地完成它,并且可能使用更适应的 NSArray 子类),同时+arrayWithArray:
将创建一个新实例NSArray
(嗯,实际上是 Foundation 用于数组的具体类)并提供它与初始对象中的对象列表相同。它还将添加一个额外的自动释放。
(非常-copy
非常)可能更有效。
事实上,对于 immutable NSArrays
,-copy
它只是在做-retain
,所以它甚至不需要创建一个新实例。
NSMutableArray *arr = [NSMutableArray array];
for ( int i = 0; i < 10000; i ++)
{
[arr addObject:@(i*1000000ULL)];
}
// MARK
// arr = (id)[NSArray arrayWithArray:arr];
NSTimeInterval t = [NSDate timeIntervalSinceReferenceDate];
NSArray *res = nil;
for ( int i = 0; i < 10000; i ++)
{
res = [arr copy];
}
NSLog(@"time A: %f", [NSDate timeIntervalSinceReferenceDate] - t);
t = [NSDate timeIntervalSinceReferenceDate];
for ( int i = 0; i < 10000; i ++)
{
res = [NSArray arrayWithArray:arr];
}
NSLog(@"time B: %f", [NSDate timeIntervalSinceReferenceDate] - t);
时间 A:1.572795,时间 B:1.539150,B [NSArray arrayWithArray:] 总是更快,但时间差非常小。但是,如果我们取消注释“MARK”并从 NSArray 而不是 NSMutableArray 获取副本,我们将有其他运行时 A:0.000473 时间 B:1.548400 结果:约快 3200 倍
其中之一可能更快。运行它们一百万次,看看是否有人获胜。
在NSArray
vs的情况下NSMutableArray
,被复制的不可变数组不必实际返回副本,因为它无法更改。但是,如果您有一个可变数组,则需要复制它,因为您可以更改原始数组。当然,做一个可变副本总是需要返回一个新对象。
在您的整个应用程序中,与正在发生的其他事情相比,速度和内存差异可能并不重要。
在 Swift 中,情况非常不同。感谢 Swift 的新开源 Foundation,我们知道虽然init(array:)
使用给定的项目(如果有)创建一个新数组,但copy()
只需返回self
.
public override func copy() -> AnyObject {
return copyWithZone(nil)
}
public func copyWithZone(zone: NSZone) -> AnyObject {
return self
}
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSArray.swift#L82
public convenience init(array: [AnyObject]) {
self.init(array: array, copyItems: false)
}
public convenience init(array: [AnyObject], copyItems: Bool) {
let optionalArray : [AnyObject?] =
copyItems ?
array.map { return Optional<AnyObject>(($0 as! NSObject).copy()) } :
array.map { return Optional<AnyObject>($0) }
// This would have been nice, but "initializer delegation cannot be nested in another expression"
// optionalArray.withUnsafeBufferPointer { ptr in
// self.init(objects: ptr.baseAddress, count: array.count)
// }
let cnt = array.count
let buffer = UnsafeMutablePointer<AnyObject?>.alloc(cnt)
buffer.initializeFrom(optionalArray)
self.init(objects: buffer, count: cnt)
buffer.destroy(cnt)
buffer.dealloc(cnt)
}
https://github.com/apple/swift-corelibs-foundation/blob/master/Foundation/NSArray.swift#L116
所以,显然,copy()
速度更快,现在你知道它们是如何工作的了!(仅在 Swift 中)