2013-02-13 4 views

Antwort

23

Welche davon ist schneller?

Mach dir keine Sorgen. Vorzeitige Optimierung

Der Hauptunterschied: Der erste Ansatz führt zu einer automatisch freigegebenen "Kopie", die Sie nicht besitzen und nicht freigeben müssen, während Sie das in der zweiten Zeile erstellte Objekt besitzen. Beide Arrays werden übrigens unveränderlich sein.

+0

Was ist mit ARC? –

+0

Ich würde sagen, mit ARC die zweite, also ist es nicht automatisch freigegeben, und daher nicht herum, bis der Autorelease-Pool geleert wird. Aber es sei denn, Sie erstellen viele Arrays im selben Runloop (oder in einem @ Autoreleasepool), das ist eine vorzeitige Optimierung :) –

1

Einer von ihnen ist wahrscheinlich schneller. Führe sie eine Million Mal und schau, ob jemand gewinnt.

Bei NSArray vs NSMutableArray muss ein unveränderbares Array, das kopiert wird, keine Kopie zurückgeben, da es nicht geändert werden kann. Wenn Sie jedoch ein veränderbares Array haben, müsste es kopiert werden, da Sie das Original ändern könnten. Und natürlich muss eine veränderbare Kopie immer ein neues Objekt zurückgeben.

In Ihrer gesamten App wird der Unterschied in Geschwindigkeit und Speicher wahrscheinlich keine Rolle spielen, verglichen mit allem anderen, was gerade passiert.

7

Der Unterschied zwischen den beiden ist, dass letztere beibehalten werden. Ersteres wird automatisch veröffentlicht.

Beide Versionen machen eine flache Kopie des Arrays.

NSMutableArray *notMutableReally = [NSArray arrayWithArray:aMutableArray]; 

Sollten Sie eine Compiler-Warnung, wie Sie ein NSArray zu einem NSMutableArray zuweisen werden versuchen.

Verwendung.

NSMutableArray *mutableArrayCopy = [NSMutableArray arrayWithArray:aMutableArray]; 

Was ist schneller? Mach dir keine Sorgen, sie sind alle viel schneller als der Rest der Sachen, die du machen wirst. Überprüfen Sie mit Instrumenten, wenn Sie wirklich interessiert sind.

4

Der wesentliche Unterschied besteht darin, dass -copy weiß besser, wie sich selbst zu kopieren (es tun kann effizienter und vielleicht nutzen, um eine angepasste Unterklasse von NSArray), während +arrayWithArray: eine neue Instanz von NSArray schaffen wird (na ja, die konkrete Klasse in der Tat verwendet von Foundation für Arrays) und füttern Sie es mit der gleichen Liste von Objekten aus dem ursprünglichen Objekt. Außerdem wird eine zusätzliche Autorelease hinzugefügt.

Also -copy ist (sehr, sehr) wahrscheinlich effizienter.

In der Tat für unveränderlich NSArrays, -copy tun nur -retain, so dass es der Mühe nicht einmal eine neue Instanz zu schaffen.

+0

Dies ist nicht genau. Ein neues Array wird erstellt, wenn Sie eine Kopie erstellen. – thierryb

+1

Sie können es mit einem einfachen Test-Tool versuchen (nicht zu erwähnen, dass ich andere sehr gute Gründe habe zu glauben, dass ich hier richtig bin) – Julien

+0

@Julien wie Sie scheinen sehr gut in Foundation-Klassen, was ist der richtige Weg zur Überprüfung, ob ein NSArray , NSDictionary, etc. ist veränderbar? Es gab bereits anderswo Diskussionen, aber keine gute Antwort gefunden? (-isKindOfClass: wird gesagt, um unzuverlässig zu sein, nicht sicher über -respondsToSelector: @selector (addObject :) Zeug?) auf der Suche nach dem richtigen Weg ... danke! –

21

Zusätzlich zu den anderen Antworten, auch zu beachten, dass, wenn someArray null ist, die erste Zeile array Punkt auf ein leeres Array machen wird und die zweite wird es Punkt zu null machen. Dies könnte insbesondere bei veränderbaren Arrays ein wichtiger Unterschied sein.

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); 

Zeit A: 1,572795, Zeit B: 1,539150, B [NSArray arrayWithArray:] immer schneller, aber Zeitdifferenz sehr klein. Aber wenn wir „MARK“ Kommentar- und erhalten kopieren von NSArray statt NSMutableArray werden wir andere Laufzeit haben A: 0,000473 Zeit B: 1,548400 Ergebnis: ~ 3200x mal schneller

1

In Swift, es ist sehr unterschiedlich. Dank der neuen Open-Source-Foundation für Swift wissen wir, dass während init(array:) ein neues Array mit den gegebenen (falls vorhanden) Elementen erstellt, copy() einfach self zurückgibt.

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

Also, natürlich, ist copy() schneller, und jetzt wissen Sie, wie sie beide arbeiten! (Nur in Swift)

+1

Gut zu wissen, wie dieses Zeug in Swift funktioniert :) –