测试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来进行释放。

posted @ 2012-07-19 17:59  zenny_chen  Views(449)  Comments(0Edit  收藏  举报