Lambda表达式是C++ 11新特性之一,总的来说就是一个函数,第一眼看到这个函数也是一脸懵逼,怎么没有见到过这个写法?于是查找了一些资料,按照我的理解记录一下
Lambda基本语法
Lambda标准语法定义:
[capture] (parameters) mutable ->ret-type{body};
说明:
1.[capture]:捕捉列表。捕捉列表总是出现在Lambda函数的开始处。实际上,[]是Lambda引出符。编译器根据该引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用,捕获列表可以是下面的类型:
1.[var]表示值传递方式捕捉变量var;
2.[=]表示值传递方式捕捉所有父作用域的变量(包括this);
auto f1 = [=]{return a + 1;}; //按值捕获a
Cpp3.[&var]表示引用传递捕捉变量var;
4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this);
auto f2 = [&]{return a + 1;}; //按引用捕获a
Cpp5.[this]表示值传递方式捕捉当前的this指针。
6.[ ]表示不捕获任何变量。
捕获列表也可以组合:
- 1.[=,&a,&b]表示以引用传递的方式捕捉变量a和b,以值传递方式捕捉其它所有变量;
- 2.[&,a,this]表示以值传递的方式捕捉变量a和this,引用传递方式捕捉其它所有变量。
如果重复是不允许的:
1.[=,x]这里已经以值传递方式捕捉了所有变量,但重复捕捉x;
2.[&,&this]&已经相当于以引用传递方式捕捉了所有变量,再捕捉this则会重复。
2.(parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号“()”一起省略;
3.mutable:mutable修饰符。默认情况下,Lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空);
4.->ret-type:返回类型。可以指定,也可以不指定,不指定编译器则会自动推导返回类型,例如:
[](double x ) {int y = x ;};
Cpp如果函数有多个返回值,编译器不能推导,需要自行添加,例如:
[](double x )->double{int y = x ;return x - y;};
Cpp5.{body}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
Lambda函数具体使用
1.其中上面讲到了父作用域,简单来说就是包含Lambda函数的{ }
代码段。
2. 另外,Lambda是匿名函数,但通常会给它取名,例如:
auto f = [](int x ) {return x % 3 ==0;};
这样就可以在程序中更方便的调用Lambda函数了:
#include <iostream>
using namespace std;
int main()
{
int a = 10, b = 5;
auto f = [=]{return a + b;}; //[=]按值捕获了a和b
cout << f() << endl; //值为15
return 0;
}
3.保持Lambda函数引用的变量的值是最新的:
#include <iostream>
using namespace std;
int main()
{
int a = 8;
auto f1 = [=]{return a + 1;}; //按值捕获a
auto f2 = [&]{return a + 1;}; //按引用捕获a
cout << f1() << endl;
cout << f2()<< endl;
a++;
cout << f1() << endl;
cout << f2() << endl;
return 0;
}
程序结果:
8
8
8
9
按值捕获可以看作Lambda函数生成了一个const类型的变量,它的值是不会因为外部更新而更新的;同样引用捕获相当于调用a的内存地址,保证实时更新,如果想要Lambda函数在调用时访问的外部变量是最新的,我们就需要使用按引用捕获。
如果非要做到修改值捕获变量的值,就可以使用mutale关键字;默认情况下,lambda函数是一个const函数,而mutable也可以取消常量性,例如:
#include <iostream>
using namespace std;
int main()
{
int a = 10;
auto f = [=]()mutable{return a *= 10;};//取消常量性
cout << f() << endl;
return 0;
}
程序结果:
100
mutable 修饰的 Lambda 表达式就算没有参数也要写明参数列表,这里的()
表示没有省略,只是没有参数而已。