麻痹,今天不知道怎么了,我竟然失眠了。本来在看电视,突然就想着写一篇关于Lambda的博文,一来算是打发时间,二来算是对自己白天的学习做一个总结吧。Lamba是C++11中最新的功能,Lamba说白了其实就是一个匿名函数,可以包含语句和定义。
Lambda通用格式
C++ 中的Lambda函数的一般表达方法为:
[捕获列表](参数列表) -> [返回类型] {函数体}
其中捕获列表是一个Lambda函数所在的函数中使用的变量列表。其他的部分和普通的函数是一样的,但是要注意的是C++的Lambda的返回值是在参数列表的后面,并且由一个->隔开。
Lambda使用举例
Lamba的学习和使用也很容易,一个简单的Lambda函数如下所示:
[](void)->void { std::cout<<"Hello,World"
<<std::endl; };
可以将一个Lambda函数保存起来,在需要的时候进行调用,可使用C++的auto(自动类型推导)保存Lambda,如下所示:
auto func = [](void)->void {std:: cout<<"Hello,World"<<std::endl;};
func();
这样,通过调用func就能输出”Hello,World”了。
Lamba与函数指针
以上函数等价于一个以下代码,如下所示:
void print(void)
{
std::cout<<"Hello,World"<<std::endl;
return ;
}
void(*func)(void) = &print;
func();
从以上两段代码可以看出,Lambda相比函数指针的优点:
1. Lambda可以直接定义函数体,而不是指向另外一个函数,而函数指针不可以直接定义函数体,而只能指向另外一个函数。
2. Lambda可以通过捕获列表直接使用并修改所在函数的局部变量,而函数指针则没有这样的功能,就像是内嵌函数。
Lambda捕获列表
Lambda就是通过捕获列表来使用并修改所在函数的局部变量。捕获列表总共有以下几种方式
1. []:空捕获,Lambda无法使用所在函数的变量
2. [变量列表]:以值捕获方式捕获指定的变量,而其他变量则不能被捕获,无法在Lambda内部使用。
3. [&变量列表]: 以引用捕获的方式捕获指定的变量,而其他变量则不能被捕获,无法在Lambda内部使用。
4. [=, 变量列表]:变量列表中指定的以引用的方式捕获,而其他的则以值的方式捕获。
5. [&, 变量列表]:变量列表中指定的以值的方式捕获,而其他的则以引用的方式捕获。
6. [=]:以值捕获的方式捕获所在函数的变量,可以直接在Lambda函数体中使用所在函数的所有局部变量而无需在捕获列表中逐个声明。
7. [&]:以引用捕获的方式捕获所在函数的变量,可以直接在Lambda函数体中使用所在函数的所有局部变量而无需在捕获列表中逐个声明。
其中,最后两种被称作”隐式捕获“,而前三种则对应的被称做”显示捕获“,”隐式捕获“不指定捕获列表,由编译器从Lambda函数中使用的外部变量来推断。中间两种,隐式捕获的则以对应的方式进行捕获,而显示指定的变量则以另一种方式捕获。
使用举例如下所示:
1. 值捕获
#include <vector>
int main(void)
{
std::vector<int> vc {1,2,3,4};
auto func = [vc](void) {
for(std::vector<int>::const_iterator it = vc.begin(); it != vc.end(); ++it)
std::cout<<*it<<std::endl;};
func();
return 0;
}
从以上代码可以看到,我们以值捕获的方式捕获了一个std::vector类似于函数的值传递。Lambda捕获的是对应值的一个拷贝值而并非原值。
- 引用捕获
#include <iostream>
#include <vector>
int main(void)
{
std::vector<int> vc {1,2,3,4};
auto func = [&vc](void) {
vc[0] = 255;
for(std::vector<int>::const_iterator it = vc.begin(); it != vc.end(); ++it)
std::cout<<*it<<std::endl;
};
func();
return 0;
}
引用捕获中,捕获的则是对应变量的引用,类似于函数的引用传递,引用捕获那这个有什么用呢?其实像iostream这样的,无法被拷贝的对象则必须使用引用捕获的方式。
其实我之前也一直以为引用捕获是可以修改所引用的对象的值的,但是经过自己的实验之后才发现原来是不可以的。
mutable关键字
那么如果想要在Lambda中修改变量的值怎么办呢?我们可以在Lambda的函数体之前加上一个mutable关键字,mutable的意思是“可变的”,指明了值可以被修改。如下所示:
#include <iostream>
#include <vector>
int main(void)
{
std::vector<int> vc {1,2,3,4};
auto func = [vc](void) mutable {
vc[0] = 255;
for(std::vector<int>::const_iterator it = vc.begin(); it != vc.end(); ++it)
std::cout<<*it<<std::endl;
};
func();
return 0;
}
这样值就会被修改成,255,2,3,4了。
结束
Lambda是其他语言中很早就已经使用的表达式,C++从11标准才引进,虽然时间有点晚, 但是总比没有强,可以做到简化很多代码的作用。