这是我参与「第四届青训营 」笔记创作活动的第6天
闭包基础
闭包本身是一个结构体,存储了函数入口地址和与之绑定的一系列环境,环境里面既有其本身内部定义的变量(约束变量),又包含从外部捕获的变量(自由变量),捕获变量的处理因实现而异。
闭包在各个语言中的表现形式
-
C++
C++中闭包的表现形式就是lambda表达式,C++11中正式添加了对其的支持
#include <algorithm> #include <cmath> void abssort(float* x, unsigned n) { std::sort(x, x + n, // Lambda expression begins [](float a, float b) { return (std::abs(a) < std::abs(b)); } // end of lambda expression ); } -
Python
python中,闭包以内部函数的形式存在
def make_multiplier_of(n): def multiplier(x): return x * n; return multiplier; -
Objective-C
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { int i = 1024; void (^printBlock)(void) = ^{ printf("%d\n", i); }; printBlock(); } return 0; }
Block 基础
- block 是闭包在 Objective-C 中的实现
- block 可以接受参数也可以有返回值
- block 可以分配在栈和堆上,也可以是全局的。分配到栈上的块可以拷贝到堆中,同标准的 Objective-C 对象一样,具备引用计数
1. 标准格式
// block声明
returnType (^blockName)(parameters);
// block赋值
^returnType(parameters) {
// do something;
};
// 示例
int (^sumBlock)(int a, int b) = ^int(int a, int b) {
return a + b;
};
int sum = sumBlock(1, 1);
block 在声明时有几个组成部分,返回值,block 的名称以及 block 传入的参数;而在给 block 赋值时,没有 block 名称这一部分,在对应的位置用返回值代替
2. 常用简写
-
省略写法
// 有返回值有入参 int (^sumBlock)(int, int) = ^(int a, int b) { return a + b; }; // 无返回值无入参 void (^printBlock)(void) = ^{ NSLog(@"Hello World!"); };对于 block 的声明来说,唯一可以省略的就是非空入参的变量名,而 block 的赋值无论是否有返回值,都可以将其省略,编译器会自动根据左侧声明检查对应的返回值是否满足要求,当函数没有入参时,还可以进一步简化为
^{}的形式 -
typedef
typedef returnType (^blockName)(parameters); typedef int (^SumBlock)(int a, int b); SumBlock block = ^(int a, int b) { return a + b; };面对过于冗长的声明,我们可以通过给常用 block 声明定义别名的形式来简化,只需要在 block 声明的左边加上关键字
typedef即可。需要注意的是,由于我们这里相当于声明了一种类型,所以blockName在typedef时的命名一般与类的命名相同,首字母大写