Abh*_*eet 6 iphone objective-c objective-c-blocks
为了理解块的词法范围,我编写了以下代码
typedef int (^ MyBlock)(void);
MyBlock b[3];
for (int i=0; i<3; i++) {
b[i]=^{return i;};
}
for (int i=0; i<3; i++) {
NSLog(@"%d",b[i]());
}
NSLog(@"----------------------------");
int j=0;
b[0]=^{return j;};
j++;
b[1]=^{return j;};
j++;
b[2]=^{return j;};
for (int i=0; i<3; i++) {
NSLog(@"%d",b[i]());
}
Run Code Online (Sandbox Code Playgroud)
我期待两个块执行的2,2,2.
任何人都可以解释一下为什么会这样?
小智 7
我假设你一直在阅读bbum关于块的帖子,并且知道你的代码不正确,因为你没有将块从堆栈复制到堆中.
那说:
for (int i=0; i<3; i++) {
b[i]=^{return i;};
}
Run Code Online (Sandbox Code Playgroud)
在每次迭代中执行以下操作:
b[i];{})已经结束,弹出堆栈中的任何内容并重置堆栈指针.堆栈在每次迭代开始时增长,并在每次迭代结束时收缩.这意味着,在相同的存储器地址被创建的所有块,即甲.这也意味着b数组中的所有元素最终都指向同一个块,即最后创建的块.您可以通过运行以下代码来测试它:
for (int i = 0; i < 3; i++) {
printf("%p", (void *)b[i]);
}
Run Code Online (Sandbox Code Playgroud)
应输出如下内容:
0x7fff5fbff9e8
0x7fff5fbff9e8
0x7fff5fbff9e8
Run Code Online (Sandbox Code Playgroud)
所有元素都指向同一个块,最后一个块在内存地址A = 0x7fff5fbff9e8中创建.
另一方面,当您执行以下操作时:
b[0]=^{return j;};
j++;
b[1]=^{return j;};
j++;
b[2]=^{return j;};
Run Code Online (Sandbox Code Playgroud)
没有复合语句为所有块定义相同的范围.这意味着每次创建块时,其地址都在堆栈的下方,有效地为每个块分配不同的地址.由于所有块都不同,因此它们正确捕获当前的运行时值j.
如果你打印前面描述的那些块的地址,你应该得到类似于的输出:
0x7fff5fbff9b8
0x7fff5fbff990
0x7fff5fbff968
Run Code Online (Sandbox Code Playgroud)
显示每个块位于不同的内存地址.
| 归档时间: |
|
| 查看次数: |
641 次 |
| 最近记录: |