[NSArray arrayWithArray:]和[NSArray copy]之间的差异

时间:2013-02-13 08:46:59

标签: objective-c cocoa-touch cocoa nsmutablearray nsarray

最近我使用数组工作很多,我很想知道......这两行之间有什么区别。

NSArray *array = [NSArray arrayWithArray:someArray];

NSArray *array = [someArray copy];

哪个更快?如果我们有NSMutableArraymutableCopy,该怎么办?

7 个答案:

答案 0 :(得分:24)

  

哪个更快?

不要担心。过早优化。

主要区别:第一种方法导致自动释放"复制"当你拥有在第二行创建的对象时,你不会拥有并且不必释放。 顺便说一下,这两个数组都是不可变的。

答案 1 :(得分:21)

除了其他答案,还要注意,当someArray为零时, 第一行将array指向一个空数组,第二行将指向空数组 它指向零。这可能是一个重要的区别,尤其是在可变数组中。

答案 2 :(得分:7)

两者之间的区别在于后者将被保留。前者将被自动释放。

两个版本都是数组的浅表副本。

NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];

在您尝试将NSArray分配给NSMutableArray时,应该给您一个编译器警告。

使用。

NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];

哪个更快?别担心,它们都比你将要做的其他东西快得多。如果你真的在乎,请查看仪器。

答案 3 :(得分:4)

主要区别在于-copy更了解如何复制自身(可以更有效地执行它并且可能使用更适应的NSArray子类),而+arrayWithArray:将创建{{1}的新实例(实际上,Foundation用于数组的具体类)并使用相同的初始对象列表来提供它。它还会添加一个额外的自动释放。

所以NSArray(非常非常)可能更有效率。

事实上,对于不可变的-copyNSArrays正在执行-copy,所以它甚至不打扰创建新实例。

答案 4 :(得分:3)

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:]总是更快,但时差非常小。 但如果我们取消注释&#34; MARK&#34;从NSArray获取副本而不是NSMutableArray我们将有其他运行时A:0.000473时间B:1.548400结果:〜3200倍快

答案 5 :(得分:1)

其中一个可能更快。运行它们一百万次,看看是否有人获胜。

如果NSArray vs NSMutableArray,则复制的不可变数组不必实际返回副本,因为它不能更改。但是,如果您有一个可变数组,则需要复制它,因为您可以更改原始数组。当然,做一个可变副本总是需要返回一个新对象。

在整个应用程序中,速度和内存差异可能与其他所有内容相比并不重要。

答案 6 :(得分:1)

在斯威夫特,它非常不同。感谢新的开源Swift基金会,我们知道虽然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)