C++11引入了lambda表达式,使得程序员可以定义匿名函数,该函数是一次性执行的,既方便了编程,又能防止别人的访问。
如图,lambda表达式由下面几个部分构成:
1. lambda-introducer (捕获字段)
2. lambda-parameter-declaration-list (变量列表)
3. mutable-specification (捕获的变量可否修改)
4. exception-specification (异常设定)
5. lambda-return-type-clause (返回类型)
6. compound-statement (函数体)
外部变量的捕获规则
默认情况下,即捕获字段为 [] 时,lambda表达式是不能访问任何外部变量的,即表达式的函数体内无法访问当前作用域下的变量。
如果要设定表达式能够访问外部变量,可以在 [] 内写入” &” 或者 “=” 加上变量名,其中” &”表示按引用访问,“=”表示按值访问,变量之间用逗号分隔,比如 [=factor, “&”total] 表示按值访问变量 factor,而按引用访问 total。
不加变量名时表示设置默认捕获字段,外部变量将按照默认字段获取,后面在书写变量名时不加符号表示按默认字段设置,比如下面三条字段都是同一含义:
[&total, factor]
[&, factor]
[=, &total]
参数列表
lambda表达式的参数列表基本和函数的一致,不过有如下限制:
1. 参数列表不能有默认参数
2. 不能是可变参数列表
3. 所有的参数必须有个变量名
如果你不提供 mutable-specification,exception-specification, 以及 lambda-return-type-clause,参数列表是也可以省略的。
如下面的表达式:
int main()
{
int x = 4;
int y = 5;
int z = [=] { return x + y; }();
}
能否修改捕获的变量
如果在参数列表后加上了 mutable,则表示表达式可以修改按值捕获的外部变量的拷贝。
异常设置
和函数一样,可以用 throw 来限定表达式能够抛出哪些异常。
返回类型
如果设置返回类型,你需要在类型名前面加上 ->。如果你只有一个返回语句的话,返回类型可以省略,编译器将会为你做出判断。
函数体
lambda表达式的函数体和普通函数大致相同。
将上图的代码片段补充完整:
int x = 10;
int y = 3;
int z ;
z = [=]()mutable throw() -> int { int n = x + y; x = y ; y = n; return n;}();
cout<<z<<endl;
cout<<"x:"<<x<<"\t"<<"y:"<<y<<endl;
运行结果为:
13
x:10 y: 3
因为是以值传递的方式访问x,y所以x,y的值并没有发生改变
现在我们队lambda表达式的基本语法已经有一些了解,下面来举几个例子
首先这个例子说明如何向lambda表达式里面传递参数:
#include <iostream>
using namespace std;
int main()
{
int n = [] (int x, int y) { return x + y; }(5, 4);
cout << n << endl;
}
运行结果为:9
通过这个例子我们可以看出,通过“函数体”后面的‘()’传入参数。
接下来这个例子可以看出,可以像调用函数一样使用lambda表达式,但是感觉这种方式和普通函数的定义与调用差不多,这里只是学习使用方式而已。
#include <iostream>
using namespace std;
int main()
{
auto f = [] (int x, int y) { return x + y; };
cout << f(21, 12) << endl;
}
运行结果为:33
Lambda表达式与STL算法一起使用,自己写测试代码的时候经常用到排序、输出数组什么的,通过下面列举的几个算法也比较方便:
#include <iostream>
#include <algorithm>
#include <ctime>
using namespace std;
int main()
{
int a[10] = {0};
srand(time(NULL));
generate(a,a+10,[]()->int { return rand() % 100; });
cout<<"before sort: "<<endl;
for_each(a, a+10, [&](int i){ cout<< i <<" "; });
cout<<endl;
cout<<"After sort"<<endl;
sort(a,a+10);
for_each(a, a+10, [&](int i){ cout<< i <<" "; });
return 0;
}
// generate();功能:用指定函数对象产生的值去给容器指定范围内元素赋值
//for_each解释
//Function for_each(InputIterator beg, InputIterator end, Function f) {
// while(beg != end)
// f(*beg++);
//}
Lambda表达式的嵌套:
#include <iostream>
int main()
{
using namespace std;
int m = [](int x)
{ return [](int y) { return y * 2; }(x) + 3; }(5);
cout << m << endl;
}
运行结果:13
以上代码在VC10和VC11上都能顺利编译通过。