测试Apple LLVM中所引入的Blocks机制是否具有闭包特性
Apple从OS X Snow Leopard开始(OS X 10.6)以及iOS 4.0开始,在其编译器内引入了Blocks语法特性,使其在C++11标准发布之前就能有Lambda表达式可用了,呵呵~但是其是否是一个闭包(Closure)呢?我们不妨可以测试一下:
#import <Foundation/Foundation.h> static void __attribute__((noinline)) (^MyTest(void))(void) { __block int a = 100; int b = 200; NSLog(@"address of a is: 0x%.16lX", (unsigned long)&a); NSLog(@"address of b is: 0x%.16lX", (unsigned long)&b); void (^block)(void) = ^void(void){ a += 300; NSLog(@"The value is: %d", a + b); NSLog(@"address of a is: 0x%.16lX", (unsigned long)&a); NSLog(@"address of b is: 0x%.16lX", (unsigned long)&b); }; a = 0; b = 0; return Block_copy(block); } int main (int argc, const char * argv[]) { @autoreleasepool { // insert code here... void (^block)(void) = MyTest(); block(); // Disrupt the stack space NSLog(@"int = %d, double = %f, long long = %lld", 100, 300.057, 12345677654321LL); block(); Block_release(block); } return 0; }
以上代码基于OS X Lion,64位应用。 我们可以通过上述输出得知,第一次调用block之前,a的值为0,b为200,b不受MyTest后面赋值的影响,而只是将定义此Block之前的值传给它。而a的变动是受到影响的。因此第一次调用block之后,a变为300,输出500;而第二次调用Block之后,a变为了600,输出800。
因此,Objective-C里的Block满足闭包的定义。但是这里有一个注意点——Blocks默认是分配在栈上的,因此如果要作为返回值返回或作为函数参数,则必须用Block_copy来进行复制。使用结束后必须用Block_release来进行释放。