不少高级语言里引入了lambda表达式的概念,即匿名函数。以往C++须要传入一个函数的时候,必须事先进行声明,视状况能够声明为一个普通函数而后传入函数指针,或者声明一个funtor,而后传入一个对象。
但这种传统方法太过复杂,一个简单的遍历输出就须要声明一个类或者函数,原本用于简化语法的东西却使语法大大复杂化。
好比一个用随机数填充数组的例子:
#include <iostream>
#include <cstdlib>
#include <iterator>
#include <algorithm>
using namespace std;ios
class mi_randc++
{
�
public:
�
mi_rand (int start_pos, int end_pos)
�
: a(start_pos), b(end_pos)
�
{}express
�
unsigned operator () ()
�
{
�
return rand() % (b-a+1) + a;
�
}ubuntu
�
private:
�
int a, b;
};数组
int main()
{
�
const int SIZE = 20;
�
int array[SIZE];
�
generate_n (array, SIZE, mi_rand (1, 30));
�
�
copy (array, array + SIZE,
�
ostream_iterator<int> (cout, " "));
�
cout << endl;
�
�
return 0;
}
示例中,generate_n的目的是使填充数组的操做简单化,但为了这种简单化却要额外声明一个类。输出数组时利用STL的确能进行语法上的简化,可是这种简化却要求对STL很是了解,并且拓展性很是差。
所幸,在c++0x标准中终于引入了lambda表达式,目前 VS 2010 和 g++ 4.5 已经进行了试验性的实现。针对上面的填充和输出操做,下面是使用lambda表达式的简化版:
#include <iostream>
#include <cstdlib>
#include <algorithm>
using namespace std;函数
int main()
{
�
const int SIZE = 20;
�
int array[SIZE];
�
generate_n (array, SIZE,
�
[] () { return rand() % 30 + 1; });spa
�
for_each (array, array + SIZE,
�
[] (int a){ cout << a << " "; });
�
�
return 0;
}指针
编译时须要注意的是,VS要求版本在2010以上,编译时须要加上 /EHsc 参数。使用g++编译的话版本要在版本4.5以上,并加上 --std=c++0x 参数。
g++目前(10年八月)的最新版本为4.51,你能够到 http://gcc.gnu.org/自行下载编译。ubuntu下能够经过 PPA for Ubuntu Toolchain Hackers直接安装二进制版本。对象
下面将阐述lambda表达式的语法,内容主要参考自 Lambda Expression Syntax。
如图,lambda表达式由下面几个部分构成:ci
lambda-introducer (捕获字段)
lambda-parameter-declaration-list (变量列表)
mutable-specification (捕获的变量能否修改)
exception-specification (异常设定)
lambda-return-type-clause (返回类型)
compound-statement (函数体)
外部变量的捕获规则
默认状况下,即捕获字段为 [] 时,lambda表达式是不能访问任何外部变量的,即表达式的函数体内没法访问当前做用域下的变量。
若是要设定表达式可以访问外部变量,能够在 [] 内写入 & 或者 = 加上变量名,其中 & 表示按引用访问,= 表示按值访问,变量之间用逗号分隔,好比 [=factor, &total] 表示按值访问变量 factor,而按引用访问 total。
不加变量名时表示设置默认捕获字段,外部变量将按照默认字段获取,后面在书写变量名时不加符号表示按默认字段设置,好比下面三条字段都是同一含义:
[&total, factor]
[&, factor]
[=, &total]
参数列表
lambda表达式的参数列表基本和函数的一致,不过有以下限制:
参数列表不能有默认参数
不能是可变参数列表
全部的参数必须有个变量名
若是你不提供 mutable-specification, exception-specification, 以及 lambda-return-type-clause,参数列表是也能够省略的。以下面的表达式:
int main()
{
�
int x = 4;
�
int y = 5;
�
int z = [=] { return x + y; }();
}
可否修改捕获的变量
若是在参数列表后加上了 mutable,则表示表达式能够修改按值捕获的外部变量的拷贝。
异常设置
和函数同样,能够用 throw 来限定表达式可以抛出哪些异常。
返回类型
若是设置返回类型,你须要在类型名前面加上 ->。若是你只有一个返回语句的话,返回类型能够省略,编译器将会为你作出判断。
函数体
lambda表达式的函数体和普通函数大体相同。
下面是lambda表达式的几个完整例子:
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// The number of elements in the vector.
const int elementCount = 9;
int main()
{
�
// Create a vector object with each element set to 1.
�
vector<int> v(elementCount, 1);
�
// These variables hold the previous two elements of the vector.
�
int x = 1;
�
int y = 1;
�
// Assign each element in the vector to the sum of the
�
// previous two elements.
�
generate_n(v.begin() + 2, elementCount - 2, [=]() mutable throw() -> int {
�
�
// Generate current value.
�
int n = x + y;
�
// Update previous two values.
�
x = y;
�
y = n;
�
return n;
�
});
�
// Print the contents of the vector.
�
for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
�
cout << endl;
�
// Print the local variables x and y.
�
// The values of x and y hold their initial values because
�
// they are captured by value.
�
cout << x << " " << y << endl;
}
#include <functional>
int main()
{
�
// Assign the lambda expression that adds two numbers to an auto variable.
�
auto f1 = [] (int x, int y) { return x + y; };
�
// Assign the same lambda expression to a function object.
�
using namespace std::tr1;
�
function<int (int, int)> f2 = [] (int x, int y) { return x + y; };
}
更多例子请参阅 Examples of Lambda Expressions,本文的数个例子也多来源于此。