一、匿名函数的基本语法
- lambda 表达式可以看成是一般函数的函数名被略去,返回值使用了一个
->
的形式表示。 - 唯一与普通函数不同的是增加了捕获列表。
[捕获列表](参数列表) -> 返回类型{
函数体
}
auto Add = [](int a, int b) -> int {
return a + b;
};
cout << Add(1, 2) << endl;
- 一般情况下,编译器可以自动推断出 lambda 表达式的返回值类型,所以我们可以不指定返回值类型。
- 但是如果函数体内有多个
return
语句时,编译器无法自动推断出返回值类型,此时必须指定返回值类型。
auto Add = [](int a, int b) {
return a + b;
};
cout << Add(1, 2) << endl;
二、捕获列表
- 有时候,需要在匿名函数内使用外部变量,所以用捕获列表来传递参数。
- 根据传递参数的行为,捕获列表可分为以下几种:
- 值捕获。
- 与参数传值类似,值捕获的前提是变量可以拷贝,不同之处则在于:被捕获的变量在 lambda 表达式被创建时拷贝,而非调用时才拷贝。
int c = 30;
int d = 40;
auto Add = [c, d](int a, int b) -> int {
cout << "d = " << d << endl;
return c;
};
d = 20;
cout << Add(1, 2) << endl;
- 引用捕获。
- 与引用传参类似,引用捕获保存的是引用,值会发生变化。
int c = 30;
int d = 40;
auto Add = [&c, &d](int a, int b) -> int {
c = a;
cout << "d = " << d << endl;
return c;
};
d = 20;
cout << Add(1, 2) << endl;
- 隐式捕获和空捕获。
- 表达式捕获。
- 上面提到的值捕获、引用捕获都是已经在外层作用域声明的变量,因此这些捕获方式捕获的均为左值,而不能捕获右值。
- C++14 之后支持捕获右值,允许捕获的成员用任意的表达式进行初始化,被声明的捕获变量类型会根据表达式进行判断,判断方式与使用
auto
本质上是相同的。auto important = std::make_unique<int>(1);
auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int {
return x + y + v1 + (*v2);
};
cout << add(3,4) << endl;
- 泛型 lambda。
- 在 C++14 之前,lambda 表示的形参只能指定具体的类型,没法泛型化。
- 从 C++14 开始, lambda 函数的形式参数可以使用
auto
关键字来产生意义上的泛型。auto add = [](auto x, auto y) {
return x + y;
};
cout << add(1, 2) << endl;
cout << add(1.1, 1.2) << endl;
- 可变 lambda。