Lambda表达式

Lambda 表达式

能够捕获作用域中的变量的无名函数对象。

基本语法

1
[capture] (parameters) mutable -> return-type {statement}

capture 捕获

capture 部分指定哪些变量被捕获,以及是值捕获还是引用捕获。空的 capture 子句 [] 只是 lambda 表达式的主体不访问封闭范围中的变量。

可使用默认捕获模式:**&** 表示所有变量都通过引用的方式捕获;**=** 表示所有变量都通过值的方式捕获。

1
2
3
4
5
int a = 0; auto f = []() { return a * 9; }; // Error, 无法访问 'a'
auto f = [a]() { return a * 9; }; // OK, 'a' 被值“捕获”
auto f = [&a]() { return a++; }; // OK, 'a' 被引用“捕获”
// 注意:请保证 Lambda 被调用时 a 没有被销毁
auto b = f(); // f 从捕获列表里获得 a 的值,无需通过参数传入 a

调用 lambda 表达式时,不需要在传递参数了,因为可以由 lambda 表达式捕获,如上 auto b = f() 代码。

parameters 参数列表

大多数情况下类似函数参数列表

1
2
auto lam = [](int a, int b) { return a + b; };
std::cout << lam(1, 9) << " " << lam(2, 6) << std::endl;

parameters 参数列表 是可选的,如果不将参数传递给 Lambda 表达式,并且其 Lambda 声明器不包含 mutable,且没有后置返回值类型,则可以 省略空括号

参数列表可以用另外一个 lambda 表达式嵌套使用。

mutable 可变规范

利用可变规范,Lambda 表达式的主体可以修改通过值捕获的变量。若使用此关键字,则 parameters 不可省略(即使为空)。

一个例子,使用  capture 捕获字句  中的例子,来观察 a 的值的变化:

1
2
int a = 0;
auto func = [a]() mutable { ++a; };

return-type 返回类型

指定 lambda 表达式的返回类型,如果没有,将会自动推断。

statement lambda 主题

和普通的函数体差不多。

1
2
3
4
5
6
7
#include <iostream>
int main() {
int m = 0, n = 0;
[&, n](int a) mutable { m = (++n) + a; }(4);
std::cout << m << " " << n << std::endl;
return 0;
}

最后我们得到输出  5 0。这是由于  n  是通过值捕获的,在调用 Lambda 表达式后仍保持原来的值  0  不变。mutable  规范允许  n  在 Lambda 主体中被修改,将  mutable  删去则编译不通过。

作者

Erial

发布于

2022-09-21

更新于

2023-02-19

许可协议

评论