引用类型在堆上的内存分配过程中有 8 字节的地址长度用来保存对象的引用计数,堆上的内存并不像栈上那样立即进行回收,系统会定时对堆上的内存进行检查,当某个实例不再被使用时,引用计数会变为 0,此时系统会自动释放实例所占用的内存空间,一旦释放就不能再访问这个实例的属性和方法。由于该过程是自动的,不需要开发人员来开辟和释放内存,因此称为自动引用计数,简称 ARC(Automatic Reference Counting)。
在构造器和析构器中分别写一个打印语句,用来标示实例的创建和销毁。
class Student {
var name: String
var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
print("创建了一个实例")
}
deinit {
print("销毁了一个实例")
}
}
声明两个变量,把它们的类型声明为 Student
的可选型,现在它们还没有被赋值。
var xiaoming: Student?
var xiaogang: Student?
通过构造器创建一个 Student
的实例,然后把这个实例赋值给第一个变量。
xiaoming = Student(name: "xiaoming", age: 12)
此时运行程序输出如下。
创建了一个实例
这次让第二个变量也引用这个实例,现在这个实例的引用计数为 2,代表着 Student
实例的内存地址被引用了两次。
xiaogang = xiaoming
下面通过给变量赋值 nil
来断开引用,首先断开一个变量的引用,现在 Student
实例的引用计数已变为 1。
xiaogang = nil
接着断开第二个变量的引用,现在没有任何属性或者变量引用这个实例了。
xiaoming = nil
可以看到中控台打印信息如下,这个类调用了析构器,代表它被销毁了,释放出了实例所占用的内存空间。
销毁了一个实例
看起来只是引用的数量增减那么简单,不过在真实的内存中,ARC 在检验某个对象的计数时不可避免的需要对堆内存进行加锁和解锁处理,也就是说无论你如何在代码层面优化代码,ARC 本身仍会带来一部分性能的损耗,这也解释了为什么值类型是更好的选择。
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。