cpp_Lambda - ShenYj/ShenYj.github.io GitHub Wiki
C11 新特性
-
有点类似于 JavaScript 中的闭包、iOS中的 Block/Clourse,本质就是函数
-
完整结构:
[capture list] (params list) mutable exception -> return type { function body }
- capture list:捕获外部变量列表
- params list:形参列表,不能使用默认参数,不能省略参数名
- mutable:用来说用是否可以修改捕获的变量
- exception:异常设定
- return type:返回值类型
- function body:函数体
-
有时可以省略部分结构
[capture list] (params list) -> return type {function body}
[capture list] (params list) { function body }
[capture list] { function body }
本质还是函数调用,只是省略一部分内容,并且限制了作用域
void test() {
/// 仅仅定义了一个没有名字的 Lambda 表达式, 不会被调用
[]{
cout << "Lanbda 函数" << endl;
);
/// 调用了一个没有名字的 Lambda 表达式
([]{
cout << "Lanbda 函数" << endl;
})();
}
Lamdba 本身就是一个函数, 所以使用函数指针来接收, 也可以直接用 C++的 auto 关键字来简化
/// 定义
void (*p)() = []{
cout << "Lanbda 函数" << endl;
);
/// 调用
p();
写法上接近于 c 的 block,区别是 block以
^
开头, 而 C++ 以[]
开头
/// 有参数有返回值
int (*b)(int, int) = [](int a, int b) -> int { return a + b; };
b(1, 2);
作为函数参数
int exec(int v1, int v2, int(*func)(int, int)) {
return func(v1, v2);
}
exec(20, 10, [](int a, int b) { return a + b });
exec(20, 10, [](int a, int b) { return a - b });
exec(20, 10, [](int a, int b) { return a * b });
exec(20, 10, [](int a, int b) { return a / b });
示例
int a = 10;
int b = 20;
/// 默认值捕获
auto func = [a, b]{
cout << a << endl;
cout << b << endl;
};
/// 地址捕获
auto func = [&a]{
a++; /// 因为是值捕获,允许修改外面的变量
cout << a << endl;
};
/// 隐式捕获(值捕获)
auto func = [=]{
cout << a << endl;
};
/// b是值捕获,其余变量地址捕获
auto func = [&, b]{
cout << a << endl;
cout << b << endl;
};
/// b是地址捕获,其余变量值捕获
auto func = [=, &b]{
cout << a << endl;
cout << b << endl;
};
/// 值捕获 + mutable 关键字
auto func = [a]() mutable {
a++; /// 不会改变外界 a 的值,修改的是内部变量 a
cout << a << endl; /// 输出结果 11
};
对比 block
c++ 11 开始提供的新特性 Lambda 表达式都是需要明确类型的,从 C++ 14 起支持泛型
就是将参数类型改为
auto
C++ 14 新特性 泛型Lambda表达式
- 泛型 Lambda 表达式
auto func = [](auto v1, auto v2) { return v1 + v2 };
cout << func(10, 20.5) << endl;
- 对捕获的变量进行初始化
/// 未初始化
int a;
auto func = [a = 10]() { /// 捕获的时候给了一个值
cout << a << endl;
}
func();
/// 外界这里仍然是未初始化的
cout << a << endl;