objective-c - 为什么 Block 使用 struct __Block_byref_object_0 而不是单个指针来捕获用“__block”修饰的变量
问题描述
这是我在文件 main.m 中的源代码
__block NSInteger blockInteger = 123;
static NSInteger staticInteger = 123;
void (^testBlock)(void) = ^() {
blockInteger++;
staticInteger++;
NSLog(@"%ld", blockInteger);
NSLog(@"%ld", staticInteger);
};
testBlock();
当我使用 clang 命令“clang -rewrite-objc main.m”时,我得到了这个
struct __Block_byref_blockInteger_0 {
void *__isa;
__Block_byref_blockInteger_0 *__forwarding;
int __flags;
int __size;
NSInteger blockInteger;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
NSInteger *staticInteger;
__Block_byref_blockInteger_0 *blockInteger; // by ref
...
};
我想知道为什么 block 使用 __Block_byref_blockInteger_0 来捕获 blockInteger 因为它使用 NSInteger 指针来捕获静态变量。__Block_byref_blockInteger_0 究竟做了什么?通过与指针比较,这个结构有什么优势?
解决方案
编译器正在创建许多结构来帮助块引用其“封闭”值。(请记住,块会复制或“包含”块外的所有值,这就是为什么块也称为“闭包”的原因。)
所以第一个结构(__Block_byref_blockInteger_0
)是创建一个对象来封装blockInteger
自动。这是因为自动变量在函数结束时消失了,但块必须能够在很久之后引用它们。
第二个结构封装__Block_byref_blockInteger_0
了块“捕获”的所有值(包括 )。这为块提供了对其所有封闭值的单一引用,这些值在创建块时复制。
现在NSInteger *staticInteger
实例值有点奇怪,因为全局地址staticInteger
不能改变。但这只是一个很小的区别,因为它仍然只是地址的副本;该地址是否可以更改并不重要。
我怀疑这是因为名称范围;在函数内声明的静态符号范围仅限于该函数。如果您查看编译器输出,您会看到您声明的每个块都会创建一个不可见的静态函数来包含其代码。由于第二个静态函数通常无法引用在另一个函数中声明的静态,因此复制静态地址是块函数访问它的唯一方法。
推荐阅读
- python - 如何访问 HasTraits/Chaco/Enable/Kiva Python GUI 应用程序的 base_pixel_scale 属性?
- javascript - per_page 不是整数类型。Woocommerce REST API Node.js
- asp.net - 如何将 google map apiKey 设置为环境变量以在 Asp.net 中确保安全 - Angular 应用程序
- c++ - OpenMP:使用“多线程”复制向量
- iis - Azure 负载平衡解决方案。将流量定向到特定虚拟机
- c# - 如何将对象的日期类型转换为另一种?
- vue-router - 带有转换的路由器链接不会第二次工作:
- bootstrap-5 - 在页面刷新时保持选定的选项卡
- python - 从 python 或 pandas 中的文件名中提取和聚合数据
- reactjs - 我的动态选择这个函数以升序形式现在我想要降序形式的函数-reactjs