20

最近我经常使用数组,我想知道..这两行之间有什么区别。

NSArray *array = [NSArray arrayWithArray:someArray];

NSArray *array = [someArray copy];

哪个更快?如果我们有NSMutableArrayandmutableCopy怎么办?

4

7 回答 7

24

哪个更快?

别担心。过早的优化。

主要区别:第一种方法会产生一个自动释放的“副本”,您不拥有也不必释放,而您确实拥有在第二行创建的对象。顺便说一句,这两个数组都是不可变的。

于 2013-02-13T08:52:18.710 回答
21

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

于 2013-02-13T09:35:17.317 回答
7

两者的区别在于后者会被保留。前者将自动发布。

两个版本都制作了数组的浅拷贝。

NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray];

应该给您一个编译器警告,因为您将尝试将 a 分配NSArray给 a NSMutableArray

采用。

NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray];

哪个更快?别担心,它们都比您将要做的其他事情快得多。如果您真的在乎,请与 Instruments 联系。

于 2013-02-13T08:56:33.753 回答
4

主要区别在于它-copy知道如何复制自己(可以更有效地完成它,并且可能使用更适应的 NSArray 子类),同时+arrayWithArray:将创建一个新实例NSArray(嗯,实际上是 Foundation 用于数组的具体类)并提供它与初始对象中的对象列表相同。它还将添加一个额外的自动释放。

(非常-copy非常)可能更有效。

事实上,对于 immutable NSArrays-copy它只是在做-retain,所以它甚至不需要创建一个新实例。

于 2013-02-13T09:00:45.630 回答
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:] 总是更快,但时间差非常小。但是,如果我们取消注释“MARK”并从 NSArray 而不是 NSMutableArray 获取副本,我们将有其他运行时 A:0.000473 时间 B:1.548400 结果:约快 3200 倍

于 2015-01-15T08:43:05.140 回答
1

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

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

在您的整个应用程序中,与正在发生的其他事情相比,速度和内存差异可能并不重要。

于 2013-02-13T08:52:00.600 回答
1

在 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 中)

于 2016-01-25T23:47:42.893 回答