Swift 引用同一个变量时数组内存地址发生变化
Swift Array memory address changes when referring to the same variable
我正在学习 Python 并想确认 Objective-C 和 Swift 中的特定行为。
测试如下:
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))")
除Swift中的地址部分外,所有结果都符合预期。在Objective-C中,array的地址在original
和modified
中保持不变,但Swift的打印结果是:
original: [1, 2, 3] address:0x00007f8ce1e092c0
array: [2, 2, 3] address:0x00007f8ce1f0c5d0
modified: [1, 2, 3] address:0x00007f8ce4800a10
我是否遗漏了什么?
Swift 中的数组具有值语义,而不是 Python 和 Objective-C 中数组的引用语义。您看到不同地址(和所有地址)的原因是每次执行 as! AnyObject
转换时,您实际上是在告诉 Swift 将您的 Array<Int>
结构桥接到一个实例NSArray
个。因为你桥接了三次,所以你得到了三个不同的地址。
您不需要考虑 Swift 数组的地址,但如果您想(暂时)获取数组缓冲区的地址,您可以这样做:
func getBufferAddress<T>(array: [T]) -> String {
return array.withUnsafeBufferPointer { buffer in
return String(buffer.baseAddress)
}
}
这让您可以看到缓冲区的写时复制正在运行:
var numbers = [1, 2, 3]
let numbersCopy = numbers
// the two arrays share a buffer here
getBufferAddress(numbers) // "0x00007fba6ad16770"
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
getBufferAddress(numbers) // "0x00007ff23a52cc30"
getBufferAddress(numbersCopy) // "0x00007fba6ad16770"
我正在学习 Python 并想确认 Objective-C 和 Swift 中的特定行为。
测试如下:
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))")
除Swift中的地址部分外,所有结果都符合预期。在Objective-C中,array的地址在original
和modified
中保持不变,但Swift的打印结果是:
original: [1, 2, 3] address:0x00007f8ce1e092c0
array: [2, 2, 3] address:0x00007f8ce1f0c5d0
modified: [1, 2, 3] address:0x00007f8ce4800a10
我是否遗漏了什么?
Swift 中的数组具有值语义,而不是 Python 和 Objective-C 中数组的引用语义。您看到不同地址(和所有地址)的原因是每次执行 as! AnyObject
转换时,您实际上是在告诉 Swift 将您的 Array<Int>
结构桥接到一个实例NSArray
个。因为你桥接了三次,所以你得到了三个不同的地址。
您不需要考虑 Swift 数组的地址,但如果您想(暂时)获取数组缓冲区的地址,您可以这样做:
func getBufferAddress<T>(array: [T]) -> String {
return array.withUnsafeBufferPointer { buffer in
return String(buffer.baseAddress)
}
}
这让您可以看到缓冲区的写时复制正在运行:
var numbers = [1, 2, 3]
let numbersCopy = numbers
// the two arrays share a buffer here
getBufferAddress(numbers) // "0x00007fba6ad16770"
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
getBufferAddress(numbers) // "0x00007ff23a52cc30"
getBufferAddress(numbersCopy) // "0x00007fba6ad16770"