различия между [nsarray arraywitharray:] и [nsarray copy]

<p>в последнее время я много работаю с массивами, и мне интересно ... в чем разница между этими двумя строками.</p><pre><code>nsarray *array = [nsarray arraywitharray:somearray]; </code></pre><p>а также</p><pre><code>nsarray *array = [somearray copy]; </code></pre><p>что из этого быстрее? что, если у нас есть <code>nsmutablearray</code> и <code>mutablecopy</code>?</p>

<blockquote> <p>что из этого быстрее?</p> </blockquote><p>не беспокойся об этом. преждевременная оптимизация.</p><p>основное отличие: первый подход приводит к автоматически выпущенной "копии", которой вы не владеете и не должны выпускать, в то время как вы владеете объектом, созданным во второй строке. кстати, оба массива будут неизменными.</p>

<p>в дополнение к другим ответам также обратите внимание, что когда <code>somearray</code> равно nil, первая строка будет указывать <code>array</code> на пустой массив, а вторая - на nil. это может быть важным отличием, особенно в изменяемых массивах.</p>

<p>разница между ними заключается в том, что последний будет сохранен. первый будет автоматически выпущен.</p><p>обе версии делают поверхностную копию массива.</p><pre><code>nsmutablearray *notmutablereally = [nsarray arraywitharray:amutablearray]; </code></pre><p>должен дать вам предупреждение компилятора, поскольку вы будете пытаться назначить <code>nsarray</code> для <code>nsmutablearray</code>.</p><p>используйте.</p><pre><code>nsmutablearray *mutablearraycopy = [nsmutablearray arraywitharray:amutablearray]; </code></pre><p>что быстрее? не волнуйтесь, все они гораздо быстрее, чем остальные вещи, которые вы будете делать. проверьте с инструментами, если вы действительно заботитесь.</p>

<p>основное отличие состоит в том, что <code>-copy</code> лучше знает, как копировать себя (может делать это более эффективно и, возможно, использовать более адаптированный подкласс nsarray), в то время как <code>+arraywitharray:</code> создаст новый экземпляр <code>nsarray</code> (ну, фактически, конкретный класс, используемый foundation для массивов) ) и передать его тем же списком объектов из исходного объекта. также это добавит дополнительный авто-релиз.</p><p>так что <code>-copy</code> (очень очень), вероятно, более эффективен.</p><p>фактически для неизменяемого <code>nsarrays</code>, <code>-copy</code> просто выполняет <code>-retain</code>, поэтому он даже не беспокоится о создании нового экземпляра.</p>

<pre><code>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); </code></pre><p>время a: 1,572795, время b: 1,539150, b [nsarray arraywitharray:] всегда быстрее, но разница во времени очень мала. <strong>но если мы раскомментируем "mark" и получим копию из nsarray вместо nsmutablearray, у нас будет другое время выполнения a: 0,000473 время b: 1,548400 результат: в 3200 раз быстрее</strong></p>

<p>один из них, вероятно, быстрее. запустите их миллион раз и посмотрите, кто победит.</p><p>в случае <code>nsarray</code> против <code>nsmutablearray</code> копируемый неизменный массив не должен фактически возвращать копию, поскольку он не может измениться. однако, если у вас есть изменяемый массив, его нужно будет скопировать, поскольку вы можете изменить оригинал. и, конечно, создание изменяемой копии всегда должно возвращать новый объект.</p><p>во всем вашем приложении разница в скорости и памяти, вероятно, не будет иметь значения по сравнению со всем, что происходит.</p>

<p>в swift все по-другому. благодаря новому open source foundation для swift мы знаем, что, хотя <code>init(array:)</code> создает новый массив с заданными элементами (если есть), <code>copy()</code> просто возвращает <code>self</code>.</p><pre class="lang-swift prettyprint-override"><code> public override func copy() -> anyobject { return copywithzone(nil) } public func copywithzone(zone: nszone) -> anyobject { return self } </code></pre><p><sup> <a href="https://github.com/apple/swift-corelibs-foundation/blob/master/foundation/nsarray.swift#l82">https://github.com/apple/swift-corelibs-foundation/blob/master/foundation/nsarray.swift#l82</a> </sup></p><pre><code> 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) } </code></pre><p><sup> <a href="https://github.com/apple/swift-corelibs-foundation/blob/master/foundation/nsarray.swift#l116">https://github.com/apple/swift-corelibs-foundation/blob/master/foundation/nsarray.swift#l116</a> </sup></p><p>итак, очевидно, что <code>copy()</code> быстрее, и теперь вы знаете, как они оба работают! <sub>(только в swift)</sub></p>