Detail on reference counting in swift memory management
- 2020-06-01 11:06:52
- OfStack
In swift, each object has a life cycle, and when the life cycle ends, the deinit() function is called to free up memory space.
Observe this 1 piece of code:
class Person{
var name: String
var pet: Pet?
init(name: String){
self.name = name
print("Person", name, "is initialized")
}
init(name: String, petName: String){
self.name = name
self.pet = Pet(name: petName)
print("Person", name, "is initialized")
}
deinit{
print("Person", name, "is deinitialized!")
}
}
class Pet{
var name: String
init(name: String){
self.name = name;
print("Pet", name, "is initialized")
}
deinit{
print("Pet", name, "is deinitialized!")
}
}
This code creates two classes, Person and Pet. In each class, there are init methods to create objects and deinit methods to free up memory space. In Person class, there are two init methods corresponding to the name of Pet class.
When we call these two methods:
var snow: Person? = Person(name: "snow", petName: "wolf")
snow = nil
The results of the two steps are:
Pet wolf is initialized
Person snow is initialized
Person snow is deinitialized!
Pet wolf is deinitialized!
You will find that the second init method is called when you create the snow object. In this method, a new Pet object is created, so Pet wolf is initialized is printed first and Person snow is initialized is printed first. When the snow object is freed, assign nil to this object, and the snow memory space will be freed, as well as the wolf memory space.
But if we call the first init method we find:
var snow: Person? = Person(name: "snow")
var wolf: Pet? = Pet(name: "wolf")
snow?.pet = wolf
snow = nil
wolf = nil
We first created an snow object, then created an wolf object, then added wolf to the snow object, but when we freed the snow object, we found:
Person snow is initialized
Pet wolf is initialized
Person snow is deinitialized!
Only the memory space of snow has been freed, but the memory space of wolf has not been freed, which is related to reference counting in swift memory management:
When we create the snow object, we create a memory space for it, and we call it a, and the snow object refers to this memory space, and the reference count of this memory space is 1,
Similarly, when we create the wolf object, we create a memory space for it, and we call it b, and then the wolf object refers to this memory space, and the reference count of this memory space is 1,
When we put snow? After.pet = wolf, then one of the attributes in snow also points to the memory space where wolf was created, so the reference count of the memory space in this article is 2.
When we free the memory space for snow = nil, the reference count of the memory space a will be 0, and the reference count of the memory space b will be 1.
When the system finds that the reference count of 1 memory space is 0, then the system will free this memory space and the memory space a will be freed.
However, the memory space b has a reference count of 1 and the system does not automatically free memory. Only when we proceed:
wolf = nil
After the operation, this memory space b will be released.
The same goes for code like this:
import UIKit
class Person{
var name: String
init(name: String){
self.name = name
print("Person", name, "is initialized")
}
deinit{
print("Person", name, "is being deinitialized!")
}
}
var person1: Person? = Person(name: "liuyubobobo")
var person2: Person? = person1
var person3: Person? = person1
Then the reference count of the memory space of person1 is 3. If this memory space is to be freed, all three objects need to be nil
If you just put person1=nil, that doesn't free up that piece of memory.