2. 从语法上看如何修改外部变量
上面代码中使用了符号=,通过拷贝方式捕获了外部变量i。
但是如果尝试在Lambda表达式中修改变量i:
[cpp]
auto func = [=] { i = 0; printf("%d\n", i); };
会得到错误:
[cpp]
testLambda.cpp: 在 lambda 函数中:
testLambda.cpp:9:24: 错误:向只读变量‘i’赋值
可见通过拷贝方式捕获的外部变量是只读的。Python中也有一个类似的经典case,个人觉得有相通之处:
[cpp]
x=10
def foo():
print(x)
x+=1
foo()
这段代码会抛出UnboundLocalError错误,原因可以参见FAQ。
在C++(www.cppentry.com)的闭包语法中,如果需要对外部变量的写权限,可以使用符号&,通过引用方式捕获:
[cpp]
int i = 1024;
auto func = [&] { i = 0; printf("%d\n", i); };
func();
反过来,将修改外部变量的逻辑放到Objective-C代码中:
[cpp]
int i = 1024;
void(^blk)(void) = ^{ i = 0; printf("%d\n", i); };
blk();
会得到如下错误:
[cpp]
main.m:14:29: error: variable is not assignable (missing __block type specifier)
void(^blk)(void) = ^{ i++; printf("%d\n", i); };
~^
1 error generated.
可见在block的语法中,默认捕获的外部变量也是只读的,如果要修改外部变量,需要使用__block类型指示符进行修饰。
为什么呢?请继续往下看 :)
3. 从实现上看如何捕获外部变量
闭包对于编程(www.cppentry.com)语言来说是一种语法糖,包括Block和Lambda,是为了方便程序员开发而引入的。因此,对Block特性的支持会落地在编译器前端,中间代码将会是C语言。
先看如下代码会产生怎样的中间代码。
[cpp]
int main(intargc, constchar * argv[])
{
int i = 1024;
void(^blk)(void) = ^{ printf("%d\n", i); };
blk();
return 0;
}