本文主要参考:
C++的lambda表达式
遇见C++ Lambda - Allen Lee - 博客园
Lambda表达式的基本语法,主要参考Lambda Expression Syntax:
- lambda-introducer(捕获字段)
- lambda-parameter-declaration-list(变量列表)
- mutable-specification(捕获的变量是否可以修改)
- exception-specification(异常设定)
- lambda-return-type-clause(返回类型)
- compound-statement(函数体)
捕获字段的说明
[] 表示捕获字段,表示不同,可以实现不同的捕获上文变量的效果。
[=]: = 表达按值访问。
[&]: & 表达引用访问。
下面是总结:
int main()
{
int x , y, z;
auto f1 = [] {}; //不捕获
auto f2 = [=] {}; //按值访问所有上文所有变量(xyz)
auto f3 = [&] {}; //引用访问所有上文变量
auto f4 = [&x, y] {}; //引用访问x,按值访问y
//等同于 [&x, =y]
auto f5 = [&, z] {};//除了个别变量(z)按值访问
/引用访问所有上文变量(xy)
auto f6 = [=, &z] {};//除了个别变量(z)引用访问
//按值访问所有上文变量
// !!auto f7 = [&, x, &z] {};
// 这样写非法,因为& 已经囊括引用捕获z了
// 正确写法:
auto f7 = [&, x] {};
}
示例代码
Lamdba表达式的产生一个匿名函数,由于类型无法确定,我们可以使用 auto 关键字进行声明:
#include<iostream>
//#include<vector>
//#include<algorithm>
//#include<functional>
//#include<typeinfo>
using namespace std;
int main()
{
auto f = [] (int x, int y) ->int
{
cout<<"it works!"<<endl;
return x+y;
};
cout<<"Now f is going to work!"<<endl;
int z = f(4, 5);
cout<<z<<endl;
int add = [=]() -> int
{
cout<<"if works?"<<endl;
return z;
}();
cout<<add<<endl;
}
输出结果:
Now f is going to work!
it works!
9
if works?
9
注意,Lambda表达式只是产生一个匿名的函数,所以,如果只是这样声明:
auto f = [] (int x, int y) ->int
{
cout<<"it works!"<<endl;
return x+y;
};
函数 f 是不会执行的。
正确的执行是:
f(4, 5);
我们可以从上面的输出结果中看到这个执行过程。(注意,最后int
add 是声明匿名函数后立刻执行的,分号前有括号”()” )
mutable的测试
#include<iostream>
using namespace std;
int main()
{
int x = 4, y =5;
int z = [=] () mutable ->int
{
x++; //如果没有 mutable关键字,编译不通过
//但这句并不实际改变x的值
return x+y;
}();
cout<<x<<endl;
cout<<z<<endl;
}
输出结果:
4
10
经常的用法
Lambda确实方便了代码的编写。
下面通过一个例子说明。这个例子生成一个动态数组,然后随机填充改数组,接着输出数组中奇数的元素,并且统计奇数的个数。
#include<iostream>
#include<vector>
#include<algorithm>
#include<ctime>
using namespace std;
int main()
{
srand(static_cast<int>(time(0)));
vector<int> vc(20);
generate(vc.begin(), vc.end(), []() -> int
{
return rand()%100;
});
int oddCount = 0;
for_each(vc.begin(), vc.end(), [&oddCount](int x)
{
if(x%2==1)
{
++oddCount;
cout<<x<<endl;
}
});
cout<<"The number of odd is: "<<oddCount<<endl;
}
输出的结果每次都不一样,其中一次:
31
9
45
61
69
1
29
35
65
77
57
3
99
The number of odd is: 13
一些问题
如何声明Lambda类型?
用auto关键字
什么时候捕获变量?
在写lambda的时候就捕获变量了,只是按照不同的方式,按值捕获的话,即使程序后面改变量依然更改,但是不影响捕获时的值。
引用捕获的话,则会持续影响。
代码示例:
#include<iostream>
using namespace std;
int main()
{
int x = 4, y = 5;
auto f =
[x, &y]() -> int
{
return x+y;
};
x += 3;
++y;
int z = f();
cout<<z<<endl;
}
输出:
10
–END–