Swift 中使用自动引用计数(ARC)机制来追踪和管理内存
强引用strong
和无主引用unowned
通过阅读源码我们知道Swift
中的class
底层继承于HeapObject
,它有个refCounts
的属性,refCounts
本质是一个Uint_64_t
类型,该属性记录了strong和unowned等信息。
islmmortal (0位)
unownedRefCount (1-31位):无主引用
isDeinitingMask (32位):是否正在进行释放
strongExtraRefCount (33-62位):强引用计数
useSlowRC (63位)
image.png
我们可以看到,强引用0、无主引用1
但是通过CFGetRetainCount
打印输出是2
原因是 CFGetRetainCount
会在执行前,先进行strong_retain
操作,在执行后,完成release_value
操作。
所以swift中CFGetRetainCount
打印的强引用计数,会比原引用计数多1
弱引用
我们可以看到引用计数是没有变化的,但是内存地址变的有些奇怪。
本质是
weak
关键字在底层创建了一个HeapObjectSideTableEntry
的对象也就是散列表,并将散列表的地址放到了refCounts
上。HeapObjectSideTableEntry
的对象包含HeapObject
中的信息,还增加了一个uint32_t
的属性,用来放弱应用的信息,并且为可选类型散列表地址=
refCounts
清楚63、62位 + 左移3位
总结
对于HeapObject来说,其refCounts 有两种
- 无弱引用:strongCount + unownedCount
- 弱引用:obct+xxx+(strongCount + unownedCount)+weakCount
HeapObjectSideTableEntry{
HeapObject *object
xxx
strong Count + unowned Count(uint64_t)//64位
weak count(uint32_t)//32位
}