Reputation: 1479
For a Node class
public class ListNode: CustomStringConvertible {
public var description: String {
return val.description + (next?.description ?? "")
}
public var val: Int
public var next: ListNode?
public init(_ val: Int) {
self.val = val
self.next = nil
}
}
with a head and nodes such that
let head = ListNode(4)
let second = ListNode(5)
let third = ListNode(1)
let forth = ListNode(8)
head.next = second
second.next = third
third.next = forth
forth.next = nil
We can remove the second node simply with
head.next = third
Will second be deallocated and the memory freed up?
Or do we need to remove the reference from second such that
second.next = nil
Upvotes: 1
Views: 471
Reputation: 273465
To actually observe the deinitialisations, we can add a deinit
block to ListNode
:
deinit {
print("\(val) deinit")
}
Your current code will not cause anything to be deinitialised, because recall that objects are only deinitialised when no other object holds a reference to it. In your current code, the global scope still has the let
constant second
that holds a reference to the second node, even after head.next = third
is executed. This causes the second node to not be deinitialised.
One way to cause the second node to deinitialise, then, is to remove all the let
constants except head
:
let head = ListNode(4)
head.next = ListNode(5) // second
head.next?.next = ListNode(1) // third
head.next?.next?.next = ListNode(8) // fourth
And then removing the second node:
head.next = head.next?.next
This causes the following to be printed:
5 deinit
indicating that the second node is deinitialised.
Setting second.next
to nil is irrelevant here, as second.next
holds a reference to the third node. Setting it to nil only decreases the number of references pointing to the third node, making an effort toward deinitialising the third node.
Upvotes: 1