• IOS中的Block与C++11中的lambda


     ios中的block 可以说是一种函数指针,但更确切的讲,其实际上其应该算是object-c对C++11中lambda的支持或者说是一个语言上的变体,其实际内容是一样的,C++的lambda我已经有简介过,现在说下ios中的block

    Block的实际行为和Function很像,最大的差别是在可以存取同一个Scope的变量值。Block实体形式如下:

    ^(传入参数列){行为主体};

    Block实体开头是“^”,接着是由小括号所包起来的参数列(比如 int a, int b, int c),return a*a;};  
    这是代表Block会回传输入值的平方值(int a 就是参数列, return a*a; 就是行为主体)。记得行为主体里最后要加“;”,因为是叙述,而整个{}最后也要加“;”,因为Block是物件实体。用法如下:

    1. int result = ^(int a){return a*a;}(5);  
    2. NSLog(@"%d", result);  


    很奇怪吧?后面的小括号里面的5会被当成a的输入值,然后经由Block输出 5*5 = 25指定给result这个变量。

    有没有简单一点的方法嗯?不然每次都写这么长?有。接下来介绍一个叫做Block Pointer的东西来简化我们的写法。

    Block Pointer是这样定义的:

    回传值(^名字)(参数列);

    比如下面的例子:

    1. //声明一个square的Block Pointer,其所指向的Block有一个int输入和int输出  
    2. int (^square)(int);  
    3. //将Block实体指定给square  
    4. square = ^(int a){ return a*a ; };  
    5. //调用方法,感觉是是不是很像function的用法?  
    6. int result = square(5);  
    7. NSLog(@"%d", result);  

    是不是变的简单了?

    也可以吧Block Pointer当成参数传递给一个function,比如:

    1. void myFunction(int (^mySquare)(int));     //function的定义,将Block作为参数  
    2. int (^mySquare)(int) = ^(int a){return a*a;};   //定义一个mySquare的Block pointer变量  
    3. myFunction(mySquare);    //把mySquare作为myFunction的参数  


    上面的三行代码其实等价于下面这行代码:

    1. myFunction( ^int(int a){return a*a;} );  


    当其作为Object-C method的传入值的话,需要把类型写在变量前面,然后加上小括号。比如下面这种写法:

    1. -(void)objcMethod:(int(^)(int))square;  //square参数的类型是int(^)(int)  


    存取变量

    1、可以读取和Block pointer同一个Scope的变量值:

    1. {  
    2.     int outA = 8;  
    3.     int (^myPtr)(int) = ^(int a){ return outA + a;};  
    4.     //block里面可以读取同一类型的outA的值  
    5.     int result = myPtr(3);  // result is 11  
    6.     NSLog(@"result=%d", result);  
    7. }  


    下面来看一段很有意思的代码:

    1. {  
    2.     int outA = 8;  
    3.     int (^myPtr)(int) = ^(int a){ return outA + a;}; //block里面可以读取同一类型的outA的值  
    4.       
    5.     outA = 5;  //在调用myPtr之前改变outA的值  
    6.     int result = myPtr(3);  // result的值仍然是11,并不是8  
    7.     NSLog(@"result=%d", result);  
    8. }  


    为什么result 的值仍然是11?而不是8呢?事实上,myPtr在其主体中用到的outA这个变量值的时候做了一个copy的动作,把outA的值copy下来。所以,之后outA即使换成了新的值,对于myPtr里面copy的值是没有影响的。

    需要注意的是,这里copy的值是变量的值,如果它是一个记忆体的位置(地址),换句话说,就是这个变量是个指针的话,

    它的值是可以在block里被改变的。如下例子:

    1. {  
    2.     NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"one", @"two", @"three", nil];  
    3.     int result = ^(int a){[mutableArray removeLastObject]; return a*a;}(5);  
    4.     NSLog(@"test array :%@", mutableArray);  
    5. }  


    原本mutableArray的值是{@"one",@"two",@"three"},在block里面被更改mutableArray后,就变成{@"one"@"two"}了。

    2、直接存取static类型的变量

    1. {  
    2.     static int outA = 8;  
    3.     int (^myPtr)(int) = ^(int a){return outA + a;};  
    4.     outA = 5;  
    5.     int result = myPtr(3);  //result的值是8,因为outA是static类型的变量  
    6.     NSLog(@"result=%d", result);  
    7.       
    8. }  

    甚至可以直接在block里面修改outA的值,例如下面的写法:

    1. {  
    2.     static int outA = 8;  
    3.     int (^myPtr)(int) = ^(int a){ outA = 5; return outA + a;};  
    4.     int result = myPtr(3);  //result的值是8,因为outA是static类型的变量  
    5.     NSLog(@"result=%d", result);  
    6.       
    7. }  


    3、Block Variable类型的变量

    在某个变量前面如果加上修饰字“__block”的话(注意,block前面有两个下划线),这个变量就称作block variable。

    那么在block里面就可以任意修改此变量的值,如下代码:

    1. {  
    2.     __block int num = 5;  
    3.       
    4.     int (^myPtr)(int) = ^(int a){return num++;};  
    5.     int (^myPtr2)(int) = ^(int a){return num++;};  
    6.     int result = myPtr(0);   //result的值为5,num的值为6  
    7.     result = myPtr2(0);      //result的值为6,num的值为7  
    8.     NSLog(@"result=%d", result);    
    9.   
    10. }  


    因为myPtr和myPtr2都有用到num这个block variable,最终num的值为7.

  • 相关阅读:
    第十二章学习笔记
    UVa OJ 107 The Cat in the Hat (戴帽子的猫)
    UVa OJ 123 Searching Quickly (快速查找)
    UVa OJ 119 Greedy Gift Givers (贪婪的送礼者)
    UVa OJ 113 Power of Cryptography (密文的乘方)
    UVa OJ 112 Tree Summing (树的求和)
    UVa OJ 641 Do the Untwist (解密工作)
    UVa OJ 105 The Skyline Problem (地平线问题)
    UVa OJ 100 The 3n + 1 problem (3n + 1问题)
    UVa OJ 121 Pipe Fitters (装管子)
  • 原文地址:https://www.cnblogs.com/imystr/p/3912642.html
Copyright © 2020-2023  润新知