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.


Related articles: