C++的Lambda表达式

介绍

C++11 开始引入了 lambda 表达式,其他语言里一般叫匿名函数。它用起来像函数,本质是编译器生成的闭包对象,可以和运算符重载得到的仿函数对照着理解。既然是对象,自然也能 new 出来(Java 的 lambda 没有这种独立类型,必须绑在函数式接口上)。定义方式如下:

1
auto 对象名 = [捕获列表](参数列表){函数体};

参数列表和返回类型都能省略,有返回值时编译器会自动推导,需要时可以写成 []() -> 类型 { ... }。

说说λ

从一段简单的代码说起。前面说过 lambda 是对象,它的类型是编译器生成的匿名类型,写不出来,所以只能用 auto 接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

int main()
{
//lambda表达式
auto lambda = []() {
cout << "hello world" << endl;
};
lambda();
}
//-------------------------------------
控制台输出:
hello world

带参数的 lambda 可以对照仿函数来理解。仿函数就是一个重载了 operator() 的类,这里简单写一个:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;

int main()
{
//lambda表达式
auto lambda = [](int a,int b) {
cout << "结果为:" << a+b << endl;
};
lambda(1,2);
}
//--------------------------------------
控制台输出:
结果为:3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;

class lambda {
public:
lambda(int a,int b) {
this->a = a;
this->b = b;
}
void operator()() {
cout << "加和为:" << this->a+this->b << endl;
}
private:
int a;
int b;
};
int main()
{
//差不多是这个意思
lambda m(2,3);
m();
}

lambda 可以匿名使用,不一定非要先用 auto 存成变量,直接当参数传给函数也行。要用参数就写在小括号里;方括号是捕获列表,常用的有 & 引用捕获、= 复制捕获和 this 捕获。

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
using namespace std;

int main()
{
//等待捕获的变量
int x = 1;
int y = 2;
//不同类型的捕获,结果不同
auto lambda1 = []() {
cout << "空捕获" << endl;
};
auto lambda2 = [=]() {
cout << "=捕获" << x << y << endl;
};
auto lambda3 = [&]() {
cout << "&捕获" << x << y << endl;
};
auto lambda4 = [&x]() {
cout << "&x捕获" << x << endl;
};
auto lambda5 = [&y]() {
cout << "&y捕获" << y << endl;
};
auto lambda6 = [x,y]() {
cout << "x,y捕获" << x << y << endl;
};
auto lambda7 = [&x,y]() {
cout << "&x,y捕获" << x << y << endl;
};
auto lambda8 = [x, &y]() {
cout << "x,&y捕获" << x << y << endl;
};
lambda1();
lambda2();
lambda3();
lambda4();
lambda5();
lambda6();
lambda7();
lambda8();
}
//------------------------------------------
输出控制台:
空捕获
=捕获12
&捕获12
&x捕获1
&y捕获2
x,y捕获12
&x,y捕获12
x,&y捕获12

方括号里写什么,决定了函数体能不能访问外部变量。留空就是什么都不捕获;= 是把变量复制一份进函数,默认不能改,想改要加 mutable,而且改的是副本;& 是引用捕获,改的就是原来的变量。

多线程里也可以用 lambda 创建线程,写法很简洁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <thread>
using namespace std;

int main()
{
//Thread
thread thread1([] {
//通过lambda创建线程对象.
cout << "thread1" << endl;
});

thread1.join();
}
//--------------------------------
thread1

结束


C++的Lambda表达式
https://blog.minloha.cn/posts/190503b9a978c82022020543.html
作者
Minloha
发布于
2022年2月5日
更新于
2022年2月5日
许可协议