我的理解:
Swift中的数组是值类型。Swift中的数组和其他集合具有CoW (复制即写)机制,因此当数组作为参数传递给函数或简单地分配给另一个变量时,Swift实际上不会创建另一个数组副本,而只是将引用传递给同一个数组。在试图写入/修改数组时,斯威夫特将创建array的一个新副本(假设原始数组引用仍被强烈保存),并对数组的新副本执行写操作。
背景:
在这个问题中,我试图存储类实例(数组中的引用类型)
class TestClass {
var name: String = "abcd"
init(name: String) {
self.name = name
}
}我正在创建TestClass的局部变量a(数组),并将其作为参数传递给someFunc。
override func viewDidLoad() {
super.viewDidLoad()
var a = [TestClass(name: "abcd"), TestClass(name: "efgh"), TestClass(name: "ijkl")]
debugPrint(UnsafePointer(&a))
self.someFunc(array: a)
}在someFunc中,我将参数赋值给另一个变量anotherArray,并在anotherArray上执行append操作。正如预期的那样,数组的CoW启动并创建了一个数组的新副本,因此array和anotherArray的内存地址是不同的。
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
debugPrint(UnsafePointer(&array))
debugPrint(UnsafePointer(&anotherArray))
}

正如预期的那样,在复制值类型时,所有内部引用类型也将被重新创建/复制,以证明
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
for var value in array {
debugPrint(UnsafePointer(&value))
}
for var value in anotherArray {
debugPrint(UnsafePointer(&value))
}
}

显然,数组的内存地址是不同的(array !=== anotherArray),而且array和anotherArray中所有项的内存地址也是不同的(array[i] !=== anotherArray[i])。
发行:
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
anotherArray[0].name = "Sandeep"
debugPrint(array[0].name)
}有了明确的理解,数组和anotherArray是两个不同的副本,而且每个数组中的引用类型也是完全不同的,如果我将anotherArray[0].name的值更改为“san深处”,那么array[0].name仍然应该是"abcd“,但它会返回"Sandeep”。

为什么会这样呢?我是不是漏掉了什么?它与数组的特殊访问器mutableAddressWithPinnedNativeOwner有什么关系吗?
mutableAddressWithPinnedNativeOwner 阵列专用访问器
如果我正确理解它,而不是简单地在特定索引处提取值,复制它,修改它并替换原来的值,就像字典中的情况一样,mutableAddressWithPinnedNativeOwner只需要访问特定索引上的值的物理内存并对其进行修改。但是,当整个数组本身被修改时,这不会有什么区别:在这里我感到困惑
完整运行代码:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var a = [TestClass(name: "abcd"), TestClass(name: "efgh"), TestClass(name: "ijkl")]
debugPrint(UnsafePointer(&a))
self.someFunc(array: a)
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
for var value in array {
debugPrint(UnsafePointer(&value))
}
for var value in anotherArray {
debugPrint(UnsafePointer(&value))
}
anotherArray[0].name = "Sandeep"
debugPrint(array[0].name)
}
}发布于 2020-05-03 20:42:03
看起来UnsafePointer(&value)返回了错误的值(可能是数组的头部或类似的东西)。我稍微改变了一下someFunc。
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
for var value in array {
debugPrint(Unmanaged.passUnretained(value).toOpaque())
}
for var value in anotherArray {
debugPrint(Unmanaged.passUnretained(value).toOpaque())
}
anotherArray[0].name = "Sandeep"
debugPrint(array[0].name)
}输出如下:
0x0000600003f29360
0x0000600003f29380
0x0000600003f29400
0x0000600003f29360
0x0000600003f29380
0x0000600003f29400
0x0000600003f29340如您所见,两个数组都包含相同的对象,这是预期的行为。数组存储对TestClass对象(而不是值)的引用,并在CoW期间复制这些引用,但对象保持不变。
https://stackoverflow.com/questions/61577518
复制相似问题