面试题答案
一键面试weak属性的实现原理
- SideTable数据结构:在Objective-C的runtime中,维护了一个
SideTable
的结构。每个SideTable
对象包含了一个weak_table_t
,这个weak_table_t
用于存储对象的弱引用信息。SideTable
是通过散列表(哈希表)的形式,根据对象的地址来索引,这样可以快速定位到某个对象对应的SideTable
。 - weak_entry_t数组:
weak_table_t
内部包含一个weak_entry_t
类型的动态数组。每个weak_entry_t
结构体记录了一个被弱引用的对象以及指向该对象的所有弱引用指针的集合。weak_entry_t
中使用referent
指向被弱引用的对象,使用referrers
数组来存储指向该对象的弱引用指针。当弱引用的对象数量增加时,referrers
数组会动态扩容。
对象最后一个强引用释放后,weak引用指向对象的变化
当对象的最后一个强引用被释放后,该对象会被释放,内存被回收。而指向该对象的所有weak
引用会自动被设置为nil
。这是weak
属性非常重要的特性,它可以避免野指针(dangling pointer)的产生,确保程序在对象释放后,所有对该对象的弱引用都是安全的。
系统对weak引用的处理
- 对象释放时:当对象的引用计数变为0,即将被释放时,runtime会根据对象的地址找到对应的
SideTable
,然后在SideTable
的weak_table_t
中找到对应的weak_entry_t
。接着遍历weak_entry_t
中的referrers
数组,将其中存储的所有弱引用指针都设置为nil
。 - 弱引用赋值时:当创建一个新的
weak
引用,即将一个对象赋值给一个weak
变量时,runtime同样会根据对象的地址找到对应的SideTable
,如果该对象对应的weak_entry_t
不存在,则会创建一个新的weak_entry_t
并添加到weak_table_t
的动态数组中。然后将新的弱引用指针添加到weak_entry_t
的referrers
数组里。