Hayden McCabe
Hayden McCabe

Reputation: 514

Is there a way to override the Copy on Write behavior for Swift arrays?

I'm working on a project where I need to work with large arrays, and by using UnsafeMutablePointers, I get a threefold speed increase over using the regular array methods. However, I believe the copy on write behavior is causing me to change instances that I do not want to be affected. For example, in the following code, I want to update the values in copyArray, but leave the original values in anArray.

import Foundation

func increaseWithPointers(_ arr: inout [Int]) {
    let count = arr.count
    let ptr = UnsafeMutablePointer(mutating: &arr)
    for i in 0..<count {
        ptr[i] = ptr[i] + 1
    }
}

var anArray = [1,2,3,4,5]
var copyArray = anArray

increaseWithPointers(&copyArray)
print(anArray)

Executing this code prints [2,3,4,5,6].

I can get around this by declaring copyArray as follows:

var copyArray = [Int](repeating: 0, count: 5)
for i in 0..<5 {
    copyArray[i] = anArray[i]
}

However, this requires writing each value twice: to zero, then to the intended value. Is there a way to efficiently guarantee a copy of an array?

Upvotes: 1

Views: 376

Answers (1)

rob mayoff
rob mayoff

Reputation: 385510

I can reproduce your problem using Xcode 9 beta 3, but not using Xcode 8.3.3. I suggest you file a Swift bug report.

This fixes the problem:

import Foundation

func increaseWithPointers(_ arr: inout [Int]) {
    arr.withUnsafeMutableBufferPointer { (buffer) in
        for i in buffer.indices {
            buffer[i] += 1
        }
    }
}

var anArray = [1,2,3,4,5]
var copyArray = anArray

increaseWithPointers(&copyArray)
print(anArray)

Upvotes: 1

Related Questions