二、lambda表达式#

1. lambda入门#

也叫做 lambda 函数 , lambda 表达式的出现目的是为了提高编码效率,但是它的语法却显得有点复杂。lambda表达式表示一个可以执行的代码单元,可以理解为一个未命名的内联函数。

1. 表达式的语法#

在编写lambda表达式的时候,可以忽略参数列表和返回值类型,但是前后的捕获列表和函数体必须包含 , 捕获列表的中括号不能省略,编译根据它来识别后面是否是lambda表达式 ,并且它还有一个作用是能够让lambda的函数体访问它所处作用域的成员。

1
2
//语法
[捕获列表](参数列表)->返回值类型{函数体}

2. 简单示例#

  • 示例1
1
2
//示例1:
[](int a ,int b)->int{return a + b ;} ; //一个简单的加法
  • 示例2

如果编译器能推断出来类型。,那么 ->int 也可以省略掉

1
[](int a ,int b){return a + b ;} ;
  • 示例3

如果不需要参数,那么参数列表页可以忽略。至此不能再精简了。

1
[]{return 3 + 5 ;};
  • 示例4

这是最精简的lambda表达式了,不过没有任何用处,等于一个空函数,没有函数体代码

1
[]{}; 

2. lambda的使用#

lambda表达式 定义出来并不会自己调用,需要手动调用。 如下面所示的,一个加法的案例

  • 使用变量接收,然后再调用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#include <iostream>
using namespace std;

int main(){
    //1. 接收lambda表达式,然后调用
    auto f = [](int a ,int b)->int{return a + b ;}; 

    //2. 调用lambda表达式
    int result = f(3,4); //调用lambda函数,传递参数

    cout << "result = " << result << endl;
    return 0 ;
}
  • 不接受表达式,直接调用
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <iostream>
using namespace std;

int main(){
    ///2. 不接收,立即调用。 后面的小括号等同于调用这个函数。
    int result= [](int a ,int b){return a + b }(3,4); 

    cout << "result = " << result << endl;    
    return 0 ;
}

3. 捕获列表的使用#

labmda表达式需要在函数体中定义,这时如果想访问所处函数中的某个成员,那么就需要使用捕获列表了。捕获列表的写法通常有以下几种形式:

形式 作用
[a] 表示值传递方式捕获变量 a
[=] 表示值传递方式捕获所有父作用域的变量(包括this)
[&a] 表示引用方式传递捕获变量a
[&] 表示引用传递方式捕获所有父作用域的变量(包括this)
[this] 表示值传递方式捕获当前的this指针
[=,&a,&b] 引用方式捕获 a 和 b , 值传递方式捕获其他所有变量 (这是组合写法)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>

using namespace std;

int main(){

    int a = 3 ;
    int b = 5;


    //值传递方式捕获 a 和 b , 在lanmbda 表示内部无法修改a和b的值
    auto f1 = [a,b]{return a + b;}; 
    cout << f1()  << endl; //打印 8


    //引用方式捕获 a 和 b  , 可以在内部修改a 和 b的值
    auto f2 = [&a,&b]{ 
        a = 30; //这里修改会导致外部的a 也跟着修改。
        return a + b;
    };

    cout << f2()  << endl; //这里打印35
    cout << "a= "<< a << endl; //再打印一次,a 变成30了

    return 0 ;
}

4. lambda 的应用场景#

编写lamdda表达式很简单,但是用得上lambda表达式的地方比较特殊。一般会使用它来封装一些逻辑代码,使其不仅具有函数的包装性,也具有可见的自说明性。

在C++ 中,函数的内部不允许在定义函数,如果函数中需要使用到某一个函数帮助计算并返回结果,代码又不是很多,那么lambda表达式不失为一种上佳选择。如果没有lambda表达式,那么必须在外部定义一个内联函数。 来回查看代码稍显拖沓,定义lambda函数,距离近些,编码效率高些。

lambda表达式其实就是一个内联函数。

1. 没有使用lambda函数#

计算6科考试总成绩。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include<iostream>

using namespace std;

int getCout(vector<int> scores){
    int result = 0 ;
    for(int s : scores){
        result += s;
    }
    return result;
}

int main(){
    vector<int> scores{80,90,75,99,73,23};
    //获取总成绩
    int result = getCout(scores);
    cout <<"总成绩是: "<< result << endl;

    return 0 ;
}

2. 使用labmda表达式#

lambda函数属于内联,并且靠的更近,也便于阅读。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include<iostream>

using namespace std;

int main(){

    vector<int> scores{80,90,75,99,73,23};
    int result2 = [&]{
        int result = 0 ;
        for(int s : scores){
            result += s;
        }
        return result;
    }();
    cout <<"总成绩是2: "<< result2 << endl;
    return 0 ;
}