介绍
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() { 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() { 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 thread1([] { cout << "thread1" << endl; }); thread1.join(); }
thread1
|
结束