对引用类型赋值感到困惑
Confused about the reference type assignment
以下是链表实现的一部分,我对语义感到困惑:
class Node<T> {
var value: T
var next: Node?
weak var previous: Node?
init(value: T) {
self.value = value
}
}
struct LinkedList<T> {
var head: Node<T>?
var tail: Node<T>?
init() { }
// what this method actually does is unimportant, but it creates a linked list from a sequence
func createChain<S>(of sequence: S) -> (head: Node<T>, tail: Node<T>)? where S: Sequence, S.Element == T {
var iterator = sequence.makeIterator()
guard let firstValue = iterator.next() else {
return nil
}
var head: Node<T>
var tail: Node<T>
var currentNode = Node(value: firstValue)
head = currentNode
while let nextValue = iterator.next() {
let newNode = Node(value: nextValue)
currentNode.next = newNode
newNode.previous = currentNode
currentNode = newNode // ?
}
tail = currentNode
return (head: head, tail: tail)
}
}
假设我要使用上面的代码创建一个链表:
let linkedList = LinkedList<Int>()
let sequence = [0, 1, 2]
let chain = linkedList.createChain(of: sequence)
在 while
循环的第一个循环中,快照如下:
while let nextValue = iterator.next() {
let newNode = Node(value: nextValue) // newNode: previous = nil, next = nil, value = 1
currentNode.next = newNode // currentNode: previous = nil, next = newNode, value = 0
newNode.previous = currentNode // newNode: previous = currentNode, next = nil, value = 1
currentNode = newNode // ?
}
当最后一行执行时,我表面上理解新节点必须不断替换当前节点以循环遍历序列的所有元素,但我不确定 [=14= 时发生了什么] 设置 newNode
。 newNode
覆盖 currentNode
没有意义,因为 currentNode
的 next
刚刚分配给 newNode
和 newNode
的 next
为零。
如果newNode
不覆盖currentNode
,newNode
的内容如何不影响currentNode = newNode
中的currentNode
?
类 是 引用类型 。这意味着 currentNode
持有对 Node
实例的引用。当您将新实例分配给 currentNode
时,您正在更改引用的对象。只要某个其他变量或 属性 持有对前一个实例的引用,它就会保留在内存中。
这就是为什么将第一个 Node
称为 currentNode
分配给 head
很重要;如果 head
没有持有引用,那么当一个新的 Node
被分配给 currentNode
时,Node
将被释放。对后续 Node
的引用由 previous
和 next
属性保存,并将它们也保存在内存中。
为了说明,我将使用 *0、*1 等表示的虚构内存地址来显示序列:
在 while
循环之前:
currentNode = Node*0(0,nil,nil)
head = Node*0(0,nil,nil)
注意currentNode
和head
指的是相同的内存地址。
第一次通过 while
循环:
currentNode = Node*0(0,nil,nil)
newNode = Node*1(1,nil,nil)
currentNode = Node*0(0,Node*1,nil)
newNode = Node*1(0,nil,Node*0)
currentNode = Node*1(nil,Node*0)
请注意 currentNode
现在引用 Node*1
。 head
仍然引用 Node*0
以及 Node*1
的 previous
值
下一次通过 while
循环:
currentNode = Node*1(1,nil,Node*0)
newNode = Node*2(2,nil,nil)
currentNode = Node*1(0,Node*2,nil)
newNode = Node*2(0,nil,Node*1)
currentNode = Node*2(nil,Node*1)
以此类推
最后,createChain
的实现有点奇怪;它 returns 一个 (head,tail)
的元组,它在一个空的 LinkedList
.
上运行
你可以将它实现为一个静态函数 returns a LinkedList
-
struct LinkedList<T> {
var head: Node<T>
var tail: Node<T>
// what this method actually does is unimportant, but it creates a linked list from a sequence
static func createChain<S>(of sequence: S) -> LinkedList<S.Element>? where S: Sequence, S.Element == T {
var iterator = sequence.makeIterator()
guard let firstValue = iterator.next() else {
return nil
}
var head: Node<S.Element>
var tail: Node<S.Element>
var currentNode = Node(value: firstValue)
head = currentNode
while let nextValue = iterator.next() {
let newNode = Node(value: nextValue)
currentNode.next = newNode
newNode.previous = currentNode
currentNode = newNode // ?
}
tail = currentNode
return LinkedList(head: head, tail: tail)
}
}
然后你可以用
创建你的链表
let sequence = [0, 1, 2]
let list = LinkedList.createChain(of: sequence)
以下是链表实现的一部分,我对语义感到困惑:
class Node<T> {
var value: T
var next: Node?
weak var previous: Node?
init(value: T) {
self.value = value
}
}
struct LinkedList<T> {
var head: Node<T>?
var tail: Node<T>?
init() { }
// what this method actually does is unimportant, but it creates a linked list from a sequence
func createChain<S>(of sequence: S) -> (head: Node<T>, tail: Node<T>)? where S: Sequence, S.Element == T {
var iterator = sequence.makeIterator()
guard let firstValue = iterator.next() else {
return nil
}
var head: Node<T>
var tail: Node<T>
var currentNode = Node(value: firstValue)
head = currentNode
while let nextValue = iterator.next() {
let newNode = Node(value: nextValue)
currentNode.next = newNode
newNode.previous = currentNode
currentNode = newNode // ?
}
tail = currentNode
return (head: head, tail: tail)
}
}
假设我要使用上面的代码创建一个链表:
let linkedList = LinkedList<Int>()
let sequence = [0, 1, 2]
let chain = linkedList.createChain(of: sequence)
在 while
循环的第一个循环中,快照如下:
while let nextValue = iterator.next() {
let newNode = Node(value: nextValue) // newNode: previous = nil, next = nil, value = 1
currentNode.next = newNode // currentNode: previous = nil, next = newNode, value = 0
newNode.previous = currentNode // newNode: previous = currentNode, next = nil, value = 1
currentNode = newNode // ?
}
当最后一行执行时,我表面上理解新节点必须不断替换当前节点以循环遍历序列的所有元素,但我不确定 [=14= 时发生了什么] 设置 newNode
。 newNode
覆盖 currentNode
没有意义,因为 currentNode
的 next
刚刚分配给 newNode
和 newNode
的 next
为零。
如果newNode
不覆盖currentNode
,newNode
的内容如何不影响currentNode = newNode
中的currentNode
?
类 是 引用类型 。这意味着 currentNode
持有对 Node
实例的引用。当您将新实例分配给 currentNode
时,您正在更改引用的对象。只要某个其他变量或 属性 持有对前一个实例的引用,它就会保留在内存中。
这就是为什么将第一个 Node
称为 currentNode
分配给 head
很重要;如果 head
没有持有引用,那么当一个新的 Node
被分配给 currentNode
时,Node
将被释放。对后续 Node
的引用由 previous
和 next
属性保存,并将它们也保存在内存中。
为了说明,我将使用 *0、*1 等表示的虚构内存地址来显示序列:
在 while
循环之前:
currentNode = Node*0(0,nil,nil)
head = Node*0(0,nil,nil)
注意currentNode
和head
指的是相同的内存地址。
第一次通过 while
循环:
currentNode = Node*0(0,nil,nil)
newNode = Node*1(1,nil,nil)
currentNode = Node*0(0,Node*1,nil)
newNode = Node*1(0,nil,Node*0)
currentNode = Node*1(nil,Node*0)
请注意 currentNode
现在引用 Node*1
。 head
仍然引用 Node*0
以及 Node*1
previous
值
下一次通过 while
循环:
currentNode = Node*1(1,nil,Node*0)
newNode = Node*2(2,nil,nil)
currentNode = Node*1(0,Node*2,nil)
newNode = Node*2(0,nil,Node*1)
currentNode = Node*2(nil,Node*1)
以此类推
最后,createChain
的实现有点奇怪;它 returns 一个 (head,tail)
的元组,它在一个空的 LinkedList
.
你可以将它实现为一个静态函数 returns a LinkedList
-
struct LinkedList<T> {
var head: Node<T>
var tail: Node<T>
// what this method actually does is unimportant, but it creates a linked list from a sequence
static func createChain<S>(of sequence: S) -> LinkedList<S.Element>? where S: Sequence, S.Element == T {
var iterator = sequence.makeIterator()
guard let firstValue = iterator.next() else {
return nil
}
var head: Node<S.Element>
var tail: Node<S.Element>
var currentNode = Node(value: firstValue)
head = currentNode
while let nextValue = iterator.next() {
let newNode = Node(value: nextValue)
currentNode.next = newNode
newNode.previous = currentNode
currentNode = newNode // ?
}
tail = currentNode
return LinkedList(head: head, tail: tail)
}
}
然后你可以用
创建你的链表let sequence = [0, 1, 2]
let list = LinkedList.createChain(of: sequence)