文章目录
block是如何截获自动变量的
小demo
int main(int argc, const char * argv[]) {
int val = 2;
void (^blk)(void) = ^{
NSLog(@"in block, val = %d", val);
};
val = 10;
blk();
NSLog(@"not in block, val = %d", val);
return 0;
}
转换成c++之后的底层代码
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int val;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _val, int flags=0) : val(_val) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int val = __cself->val; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_yy_rtbfwwy91hj81qhy92yrypy40000gn_T_main_25ce61_mi_0, val);
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = {
0, sizeof(struct __main_block_impl_0)};
int val = 2;
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, val));
val = 10;
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_yy_rtbfwwy91hj81qhy92yrypy40000gn_T_main_25ce61_mi_1, val);
一个普通Block的小demo 由此进行对比
void (^blk)(void) = ^{
NSLog(@"i am an common Block");
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_yy_rtbfwwy91hj81qhy92yrypy40000gn_T_main_e7a4eb_mi_0);
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = {
0, sizeof(struct __main_block_impl_0)};
int main(int argc, const char * argv[]) {
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
}
block的内部结构与没有截获时候的区别
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int val;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _val, int flags=0) : val(_val) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
//没有截获
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
根据转换之后的代码 block把block块表达式当中的自动变量作为一个成员变量加入到了自己的结构体中
并且
- 结构体内声明的成员变量类型和局部变量类型完全相同
- block块表达式中没有出现的局部变量不会添加
- 截获的val只是截获了该局部变量的值
该结构体的实例化函数和调用与没有截获时候的区别
__main_block_impl_0(void *fp,