lambda表达式(匿名函数)的组成:
- 捕获子句(在 c + + 规范中也称为lambda 引导)。
- 参数列表可有可无. (也称为lambda 声明符)
- 可变规范可有可无.
- 异常规范可有可无.
- 尾随-返回类型可有可无.
- lambda 体。
lambda表达式以一对中括号开始,和函数定义一样,会有参数列表,有一个函数体,里面会有return语句
Lambda表达式一般不需要说明返回值(相当于auto),有特殊情况需要说明时,则应使用‘->’
每个lambda表达式都有一个全局唯一的类型,要精准捕捉lambda表达式到一个变量中,只能通过auto声明的方式
1 #include <iostream>
2 #include <algorithm>
3 #include <vector>
4
5 using namespace std;
6
7 int Foo(int a, int b) {
8 return a+b;
9 }
10
11 int main() {
12 // []捕获列表 ()参数列表 ->返回值
13 int c = [](int a, int b) ->int{
14 //函数体
15 return a+b
16 }(1, 2);
17
18 //f为自动推导后的函数体类型
19 auto f = [](int a, int b) ->int{
20 //函数体
21 return a+b
22 };
23
24 c = f(1, 2);
25
26 return 0;
27 }
lambda作者认为所有的程序都可以归纳为lambda表达式,变为一个函数式
...
//lambda作者认为所有的程序都可以归纳为lambda表达式,变为一个函数式
//lambda表达式内部可以嵌套 -- 函数式编程:
int c = [](int n){
return [](int x){
return n+x;
}(1);
}(2);
cout << c << endl;
auto f = [](int n){
return [](int x){
return n+x;
};
};
int c = f(1)(2);
cout << c << endl;
...
mutable关键字
mutable关键字,表示可以修改按值传入的变量的副本(不是值本身),类似于不带const关键字的形参。使用mutable关键字后对按值传入的变量进行的修改,不会将改变传递到Lambda表达式之外。
例子:
int main() {
int t = 10;
auto f = [t]() {
return ++t;
};
return 0;
}
error: cannot assign to a variable captured by copy in a non-mutable lambda
在捕获列表中,只是捕获了外界的t,在表达式内部,t还是const类型,不允许修改
...
int main() {
int t = 10;
auto f = [t]() mutable{
return ++t;
};
cout << f() << endl;
cout << f() << endl;
cout << t << endl;
return 0;
}
out:
t不会改变,因为i修改的是按值传入的副本,不会影响值本身。
为什么两次调用f(),返回值会传递。
捕获列表
捕获列表,可以理解为一个参数的类型,默认情况下lambda表达式内部在默认情况下是不能使用函数外部的变量,
捕获列表就可以起到传递外部数据的作用:
- [] 不捕获任何变量。
- [&] 捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
- [=] 捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。
- [=,&foo] 按值捕获外部作用域中所有变量,并按引用捕获 foo 变量。
- [bar] 按值捕获 bar 变量,同时不捕获其他变量。
- [this] 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量。
//进阶写法
for_each(v.begin(), v.end(), [](int n) {
if(v[i] % 2 == 0) {
cout << v[i] << "是偶数" <<endl;
}else{
cout << v[i] << "是奇数" <<endl;
}
});