我正在查看数据结构,在链表方面遇到了一些我从未意识到的事情。这个特定的例子是针对链表的,但我认为这个概念将主要围绕结构中遵循引用语义(值语义(的属性。
情况如下:我声明了一个新节点,并说这个新节点和LinkedList中的head
共享相同的引用。然后,我更改head
的值。我假设,由于新节点和head
引用了内存中的相同空间,所以它们都会反映更新。然而,事实并非如此。head
显示了更新,但新节点没有。请参阅下面的代码。
public struct LinkedList<Value> {
public var head: Node<Value>?
public init() {}
/*
append, push, isEmpty, insert, pop functions
*/
}
public class Node<Value> {
public var value: Value
public var next: Node?
public init(value: Value, next: Node? = nil) {
self.value = value
self.next = next
}
}
var list = LinkedList<Int>()
list.append(1)
list.append(2)
list.append(3)
let node = list.head
list.head = list.head?.next
print(list.head) // prints 2 -> 3
print(node) // prints 1 -> 2 -> 3
由于Node
是一个类,我本以为list.head
和node
都会反映对其中任何一个的更新。为什么上面的类语义与下面的不同:
// Reference type example
class C { var data: Int = -1 }
var x = C()
var y = x // y now points to the same memory address as x
x.data = 42 // changes the instance referred to by x (and y)
println("(x.data), (y.data)") // prints "42, 42"
因为您设置了LinkedList
和Node
是类。因此,当一个变量分配给一个类变量时,它指向内存中存储该类变量的地址。
从你的这2行代码中,你可以看到
let node = list.head
list.head = list.head?.next
第一个是node = list.head
意味着node
指向存储list.head
的存储器地址。意味着此时CCD_ 13和CCD_。
第二个是list.head = list.head?.next
意味着list.head
指向存储list.head?.next
的存储器地址。意味着CCD_ 18和CCD_。
因此list.head
将内存地址更改为list.head?.next
不会影响node
当前的内存地址。
示例:A->B->C(它是来自LinkedList
的列表存储器访问(
首先,
list.head
指向存储器A然后,
node
指向存储器A然后,
list.head
被指向作为list.head?.next
的存储器B。所以
node
在存储器A中根本没有改变。