__forwarding指针
上面提到过__forwarding
指针指向的是结构体自己。当使用变量的时候,通过结构体找到__forwarding
指针,在通过__forwarding
指针找到相应的变量。这样设计的目的是为了方便内存管理。通过上面对__block
变量的内存管理分析我们知道,block
被复制到堆上时,会将block
中引用的变量也复制到堆中。
我们重回到源码中。当在block中修改__block
修饰的变量时。
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
__Block_byref_age_0 *age = __cself->age; // bound by ref
(age->__forwarding->age) = 20;
NSLog((NSString *)&__NSConstantStringImpl__var_folders_jm_dztwxsdn7bvbz__xj2vlp8980000gn_T_main_b05610_mi_0,(age->__forwarding->age));
}
通过源码可以知道,当修改__block
修饰的变量时,是根据变量生成的结构体这里是__Block_byref_age_0
找到其中__forwarding
指针,__forwarding
指针指向的是结构体自己因此可以找到age变量进行修改。
当block在栈中时,__Block_byref_age_0
结构体内的__forwarding
指针指向结构体自己。
而当block被复制到堆中时,栈中的__Block_byref_age_0
结构体也会被复制到堆中一份,而此时栈中的__Block_byref_age_0
结构体中的__forwarding
指针指向的就是堆中的__Block_byref_age_0
结构体,堆中__Block_byref_age_0
结构体内的__forwarding
指针依然指向自己。
此时当对age进行修改时
// 栈中的age
__Block_byref_age_0 *age = __cself->age; // bound by ref
// age->__forwarding获取堆中的age结构体
// age->__forwarding->age 修改堆中age结构体的age变量
(age->__forwarding->age) = 20;
通过__forwarding
指针巧妙的将修改的变量赋值在堆中的__Block_byref_age_0
中。
我们通过一张图展示__forwarding
指针的作用
因此block内部拿到的变量实际就是在堆上的。当block进行copy被复制到堆上时,_Block_object_assign
函数内做的这一系列操作。