I was learning Python and wanted to confirm a certain behavior in Objective-C and Swift.
The test was as follows:
Python
def replace(list):
list[0] = 3
print(list)
aList = [1, 2, 3]
print(aList)
replace(aList)
print(aList)
Objective-C
- (void)replace:(NSMutableArray *)array {
array[0] = @1;
NSLog(@"array: %@, address: %p\n%lx", array, array, (long)&array);
}
NSMutableArray *array = [@[@1, @2, @3] mutableCopy];
NSLog(@"original: %@, address: %p \n%lx", array, array, (long)&array);
[self replace:array];
NSLog(@"modified: %@, address: %p \n%lx", array, array, (long)&array);
Swift
var numbers = [1, 2, 3]
let replace = { (var array:[Int]) -> Void in
array[0] = 2
print("array: \(array) address:\(unsafeAddressOf(array as! AnyObject))")
}
print("original: \(numbers) address:\(unsafeAddressOf(numbers as! AnyObject))")
replace(numbers)
print("modified: \(numbers) address:\(unsafeAddressOf(numbers as! AnyObject))")
All the results came out as expected except for the address part in Swift. In Objective-C, the address of array remained the same in original
and modified
, but the print result of Swift was:
original: [1, 2, 3] address:0x00007f8ce1e092c0
array: [2, 2, 3] address:0x00007f8ce1f0c5d0
modified: [1, 2, 3] address:0x00007f8ce4800a10
Is there something I'm missing?
Arrays in Swift have value semantics, not the reference semantics of arrays in Python and Objective-C. The reason you're seeing different addresses (and addresses at all) is that every time you do an as! AnyObject
cast, you're actually telling Swift to bridge your Array<Int>
struct to an instance of NSArray
. Since you bridge three times, you get three different addresses.
You shouldn't need to think about the address of a Swift array, but if you'd like to (momentarily) get the address of an array's buffer, you can do it this way:
func getBufferAddress<T>(array: [T]) -> String {
return array.withUnsafeBufferPointer { buffer in
return String(reflecting: buffer.baseAddress)
}
}
This lets you see the buffer's copy-on-write in action:
var numbers = [1, 2, 3]
let numbersCopy = numbers
// the two arrays share a buffer here
print(getBufferAddress(numbers)) // "0x00007fba6ad16770"
print(getBufferAddress(numbersCopy)) // "0x00007fba6ad16770"
// mutating `numbers` causes a copy of its contents to a new buffer
numbers[0] = 4
// now `numbers` has a new buffer address, while `numbersCopy` is unaffected
print(getBufferAddress(numbers)) // "0x00007ff23a52cc30"
print(getBufferAddress(numbersCopy)) // "0x00007fba6ad16770"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With