Confundido/a acerca de la asignación de tipo de referencia.
A continuación se muestra una parte de una implementación de una lista enlazada y estoy confundido acerca de la semántica:
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() { }
// lo que hace en realidad este método no es importante, pero crea una lista enlazada a partir de una secuencia
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)
}
}
Digamos que quiero crear una lista enlazada usando el código anterior:
let linkedList = LinkedList<int>()
let sequence = [0, 1, 2]
let chain = linkedList.createChain(of: sequence)
En la primera iteración del bucle while
, la instantánea sería la siguiente:
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 // ?
}
Cuando se ejecuta la última línea, entiendo superficialmente que el nuevo nodo debe reemplazar al nodo actual continuamente para recorrer todos los elementos de la secuencia, pero no estoy seguro de qué está ocurriendo exactamente cuando currentNode
establece newNode
. No tiene sentido que newNode
sobrescriba a currentNode
ya que el next
de currentNode
acaba de ser asignado como newNode
y el next
de newNode
es nil
.
Si newNode
no está sobrescribiendo a currentNode
, ¿cómo es posible que el contenido de newNode
no afecte a currentNode
en currentNode = newNode
?
davy.ai
En la línea
currentNode = newNode
, la referenciacurrentNode
simplemente se actualiza para apuntar al recién creadonewNode
. Esto significa quecurrentNode
ahora apunta a una ubicación de memoria diferente a la que apuntaba anteriormente, y ya no está apuntando a la misma instancia que antes.Sin embargo, la instancia de
Node
a la quecurrentNode
apuntaba anteriormente todavía está en memoria y no ha sido modificada. Cuando se creanewNode
, sus propiedadesprevious
ynext
se establecen automáticamente ennil
, por lo que no afectan a la propiedadnext
de la instancia decurrentNode
que ya había sido establecida en la línea anterior.Por lo tanto, cuando se ejecuta
currentNode = newNode
, lo único que cambia es la referencia que contiene la variablecurrentNode
: ahora apunta al recién creadonewNode
, aunque la instancia anterior deNode
permanece sin cambios en memoria.