匿名函数是那种没有函数名但有函数体的函数,很多动态语言都支持匿名函数。在VS2010之前,VC作为一种交低级的语言不支持类似的特性,但是VS2010引入了Lambda表达式,增加了对这个特性的支持。
早在C语言的时代我们就可以使用函数指针来将函数作为一个“对象”看待,后来C++标准库的出现又引入了函数对象。但是和那些动态语言相比,C++中编写函数对象的代价还是巨大的,有时候为了实现非常简单的功能,你需要写一个类,这样代码量大大增加,而且根据程序阅读的“局部性”原则,代码阅读起来也比较费劲。Lambda表达式的引入可谓是C++进步的一大表现,从此我们可以在C++中使用匿名函数了。
先来看一个最简单的例子。
#include <vector>
#include <iostream>
#include <algorithm>
int _tmain(__in int _Argc, __in LPCTSTR* _Argv)
{
int i, sum = 0;
std::vector<int> vct;
for (i = 1; i <= 100; i++)
vct.push_back(i);
for_each(vct.begin(), vct.end(),
[&sum](int n) { // Lambda表达式定义的匿名函数
sum += n;
}
);
cout << sum << endl;
return 0;
}
这段代码我们用Lambda函数定义了一个匿名函数对象来累加for_each算法所遍历的每一个vector中的元素。看起来是不是很简洁?!
结合上文介绍的auto关键字,我们使用Lambda表达式定义了一个匿名函数fun,实现和上面的代码一样的功能。
#include <vector>
#include <iostream>
#include <algorithm>
int _tmain(__in int _Argc, __in LPCTSTR* _Argv)
{
int i, sum = 0;
std::vector<int> vct;
// 用Lambda表达式定义一个匿名函数
auto fun = [&sum](int n) {
sum += n;
};
for (i = 1; i <= 100; i++)
vct.push_back(i);
for_each(vct.begin(), vct.end(), fun);
cout << sum << endl;
return 0;
}
Lambda表达式的语法为:
[capture-clause] (parameter-list) mutable ->return-type
{
function-body
}
其中,capture-clause表示函数体中需要使用的作用域内的变量的引用或者值,可以为空。上面的代码中我引用了作用域内的sum变量,那么使用了&前缀来表达这个需求。如果我想使用sum的值,那么只要写成[sum]即可,不需要加&前缀。如果我写成[&sum,i],那么表示我想引用sum并使用i的值(而不是i的引用)。有几个需要注意的地方,那么capture-clause支持[&],和[=],分别表示引用所有可以引用的变量和使用所有可以使用的变量的值,除非后面特别指定(比如[&,i]或者[=,&i])。
parameter-list和普通函数的参数表一样。
当capture-clause中有使用某个变量的值的时候,有时候需要修改这个值,那么用mutable关键字来修饰。但是不用担心,对这个值的修改仅仅是修改了它的值的副本,这个类似于函数参数的传值。下面的代码运行后,n的值还是0。
int n = 0;
auto fun = [=]() mutable {
n = 1;
};
fun();
我们知道普通函数可以有返回值也可以没有,Lambda表达式中也支持。只不过写法不同,当Lambda表达式中想用返回值,需要使用“->return-type”的形式,比如,
From: http://jgshining.me/blog/2010/05/c%E5%BC%80%E5%8F%91%E8%80%85%E7%9A%84vs2010%EF%BC%88%E4%BA%8C%EF%BC%89%E2%80%94%E2%80%94-lambda-%E8%A1%A8%E8%BE%BE%E5%BC%8F/