C++11:lambda表达式

这个实现的效果类似于匿名函数,不想C++98/03那样一个函数所有人都能调用,不公开不必要的接口,提高程序安全性。

首先来写个最简单的lambda表达式。

[]{};

对,5个字符就成为了一个lambda表达式了,虽然并没卵用,不过至少跨出了一步。这个lambda表达式实际上是精简后的表达式。不加以精简的话,原表达式应该像这样:

[](){};

看起来挺简单的,我也这么觉得微笑

解释下,首先一对方括号代表捕获列表,含义后面再解释。然后是一对圆括号,代表lambda函数的参数列表,当参数为空可省略这对圆括号,就像上面5个字符的lambda表达式这样。接下来是一对大括号,这个和函数的大括号没什么区别了,里面可以加代码,可以加return。

下面我们来实现一个lambda表达式,用来计算两个int数字的和

auto sum = [] (int a, int b) {
	return a+b;
};
这儿为了方便,使用auto自动生成类型。调用方式也简单,直接   sum(3,5);   就行了,返回的类型为自动推导类型。
关于这个类型,目前我知道的,有两种形式保存,一种是通过函数指针。这种方式只能对捕获列表,也就是那对中括号为空的lambda函数进行保存,代码如下:

#include <iostream>
using namespace std;

using pSum = int (*)(int, int);//C++11新特性,类型重定义,效果与  typedef int (*pSum)(int, int);  完全相同

int main (int argc, char* argv []) {
	pSum sum = [] (int a, int b) {
		return a + b;
	};
	cout << sum (3, 5) << endl;
	return 0;
}
结果呐,对你没猜错,就是8。
接下来就是针对捕获列表不为空的情况了,下面说下捕获列表的作用。捕获列表是在函数中定义lambda表达式时,用于方便获取局部变量的值或引用。

#include <iostream>
using namespace std;

int main (int argc, char* argv []) {
	int i = 5;
	[&i] () { i = 3; }();
	cout << i << endl;
	return 0;
}
定义lambda后直接调用,直接在lambda函数后面加一对圆括号传参就行了。这儿我定义了一个变量i,然后通过捕获列表传入i的引用,然后对i进行重新赋值。程序运行结果为3。关于捕获的引用传递与值传递的区别是,值传递后变量不可更改,引用传递后变量可修改。上面我传的是引用,使用“&i”,值传递直接写个 i 就行了。

这儿可以写多个引用或值传递。如果一次性需要引入所有局部变量,那么写个 [&] 代表引用所有,写个 [=]代表传递所有的值。传值后的变量不可修改,有办法能加个可修改属性,如下代码:

#include <iostream>
using namespace std;

int main (int argc, char* argv []) {
	int i = 5;
	[i] () mutable { i = 3; }();
	cout << i << endl;
	return 0;
}
mutable表示可以修改值传递的数据,但不影响函数的局部变量。上面这代码的程序运行结果还是5。
那么这样的lambda表达式如何存储呢?这得通过std::function。如下代码演示如何存放包含捕获的lambda表达式

#include <iostream>
#include <functional>
using namespace std;

int main (int argc, char* argv []) {
	function<int (int, int)> f = [] (int a, int b) { return a + b; };
	cout << f (3, 5) << endl;
	return 0;
}
计算两个数字之和的lambda表达式,除了通过函数指针外,也可通过function存储。这儿没有写捕获列表,写了也能存储。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章