lambda表达式(匿名函数)的组成:

lambda表达式 java fliter Lambda表达式C_lambda表达式

  1. 捕获子句(在 c + + 规范中也称为lambda 引导)。
  2. 参数列表可有可无. (也称为lambda 声明符
  3. 可变规范可有可无.
  4. 异常规范可有可无.
  5. 尾随-返回类型可有可无.
  6. 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:

lambda表达式 java fliter Lambda表达式C_函数体_02

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;            
        }
    });