一、Lambda表达式是什么?
Lambda表达式是C++11引入的一个很重要的特性,它是一个可调用对象,定义了一个匿名函数,并且可以捕获一定范围内的变量。
1、lambda表达式的形式
lambda的一般形式为:
[捕获列表](参数列表)-> 返回类型{ 函数体;};
①lambda采用返回类型后置写法:
auto f = [](int a) -> int {
return a+1;
};
②lambda利用return自动推导返回类型:
auto f = [](int a) {return a};
2、捕获列表的用法
[捕获列表],lambda表达式通过这个捕获列表来捕获一定范围内的变量
(1)[ ]:不捕获任何变量
int i = 9;
auto f1 = []
{
return i; // 报错,因为i是外部变量,无法捕获,
// 但如果改成static int i的话则可以捕获
}
(2)[&]:按引用捕获
#include <iostream>
using namespace std;
int main() {
int i = 9;
auto f1 = [&] {
i = 5; // 使用的是外面捕获的变量,并且是以引用传递
return i;
};
cout << f1() << endl; // 返回i的值为5
cout << i << endl; // i的值以及变成5
}
(3)[=]:按值捕获
#include <iostream>
using namespace std;
int main() {
int i = 9;
auto f1 = [=] {
i = 5; // 报错,因为是按值捕获,所有不能修改i的值,只能拿来使用
return i;
};
}
3、lambda表达式延迟调用细节分析
请看下面一段代码:
#include <iostream>
using namespace std;
int main() {
int i = 5;
auto f = [=] {
return i;
};
i = 10;
cout << f() << endl; //输出的数值为5,而不是10
}
解释:当到auto这一行的时候,i的值已经被复制到f这个lambda表达式中了;但如果改成引用捕获的话,则输出的值为10。
4、lambda表达式的类型和存储
C++11中,lambda表达式的类型被称为闭包类型。正常来说C++是不允许在函数内定义函数的,但是通过lambda表达式,相当于在函数中定义函数了。函数闭包就是函数中的函数。
闭包,本质上其实就是lambda表达式创建的运行期对象。例如前面代码中的f。
lambda表达式相当于定义了一个新类型,并且生成了一个匿名的对象(闭包)。
二、比较函数指针、函数符和Lambda表达式
函数指针、函数符和Lambda表达式都可以当作函数对象,下面这个例子使用三种方法给STL算法传递信息:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/* 定义了一个函数,能被3整除则返回true */
bool FuncPtr(int x) {
return x % 3 == 0;
}
/* 定义了一个函数符,功能同上 */
class FuncChar {
public:
bool operator() (int x) {
return x % 3 == 0;
}
};
/* 定义了一个lambda表达式(匿名函数),功能同上 */
auto FuncLambda = [](int x){return x % 3 == 0l;};
int main() {
vector<int> nums = {1, 2, 3, 4, 5, 6};
int counts1 = count_if(nums.begin(), nums.end(), FuncPtr); // 传进去的是函数指针
cout << "nums has " << counts1 << " can be 3 divided" << endl;
int counts2 = count_if(nums.begin(), nums.end(), FuncChar()); // 传进去的函数符
cout << "nums has " << counts2 << " can be 3 divided" << endl;
int counts3 = count_if(nums.begin(), nums.end(), FuncLambda); // 传进去的lambda表达式
cout << "nums has " << counts3 << " can be 3 divided" << endl;
return 0;
}