1 lambda表达式
C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式)。Lambda表达式把函数看作对象。Lambda表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。Lambda 表达式本质上与函数声明非常类似,Lambda表达式具体形式如下:
[capture](parameters) mutable ->return-type{statement}
例如:
[](int a, int b) -> int { return a + b; };
参数介绍:
- [capture]:捕捉列表。捕捉列表总是出现在lambda表达式的开始处。事实上,[]是lambda引出符。编译器根据该引出符判断接下来的代码是否是lambda函数。捕捉列表能够捕捉上下文中的变量供lambda函数使用。
- (parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同括号()一起省略。
- mutable:mutable修饰符。默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。
- ->return_type:返回类型。用追踪返回类型形式声明函数的返回类型。出于方便,不需要返回值的时候也可以连同符号->一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导。例如只用一个return语句时可以自动推导。
- {statement}:函数体。内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。在lambda函数的定义式中,参数列表和返回类型都是可选部分,而捕捉列表和函数体都可能为空,C++中最简单的lambda函数只需要声明为:[]{};
1.2 变量捕获
Lambda 函数可以引用在它之外声明的变量. 这些变量的集合叫做一个闭包. 闭包被定义在 Lambda 表达式声明中的方括号 [] 内。这个机制允许这些变量被按值或按引用捕获。还可以隐式捕获,让编译器根据函数体中的代码来推断需要捕获哪些变量,如下图的例子:
- [] // 沒有定义任何变量。使用未定义变量会引发错误
- [x, &y] // x以传值方式传入(默认),y以引用方式传入
- [&] // 任何被使用到的外部变量都隐式地以引用方式加以引用
- [=] // 任何被使用到的外部变量都隐式地以传值方式加以引用
- [&, x] // x显式地以传值方式加以引用。其余变量以引用方式加以引用
- [=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用
- [this] //捕获this指针,可以访问类的成员变量和函数
std::vector<int> some_list;
int total = 0;
for (int i = 0; i < 5; ++i) some_list.push_back(i);
std::for_each(begin(some_list), end(some_list), [&total](int x)
{
total += x;
});
此例计算 list 中所有元素的总和。变量 total 被存为 Lambda 函数闭包的一部分。因为它是栈变量(局部变量)total 引用,所以可以改变它的值。
网友评论