跟python一样。。。C++11终于也有了lambda函数了。。。
个人感觉挺好用的,以下是个人的一些理解
基本的Lambda函数:
[捕获的变量](参数)->返回值类型{函数体}
调用方法:
[捕获的变量](参数)->返回值类型{函数体}(实参1,……,实参N);
各部分的解释:
参数是指传递给lambda函数的参数,如可以(int a) 、(int a,int b) 、(int a,……,int z)当然也可以是无参数的();
返回值类型就是lambda函数返回的那个值的类型(= =,好像解释了等于没解释);
函数体是标识函数的实现;
返回值类型、参数、函数体都跟平常的函数差不多,只是返回值类型 换了个位置且前面多了个->,它们都可以被省略,如下面形式
[捕获的变量](){}
注:当编译器可以自动推断出返回值类型才可以将返回值类型省略。
[捕获的变量]是lambda函数的开始,方括号[]不可以省略,但“捕获的变量"是可以省略的,其是用来传递给编译器自动生成的函数对象类的构造函数的。
它可以捕获从作用域开始到lambda函数所在行的所有局部变量,使lambda函数能使用函数体外被捕获的那些局部变量。为什么是局部变量呢?因为它不能捕获全局变量(这句话有点SB,请无视。)如下面的例子就是错误的:
int a=10;
int main()
{
//尝试捕获一个全局变量
std::cout<< [a](){return a;}()<<std::endl; //这里的[a]后面会讲解;
}
编译器提示错误:
它可以是下面的几种形式:
[] //不捕获任何局部变量,尝试使用任何未捕获的局部变量是非法的,如下面代码:
int main()
{
int a=10;
int b=3;
std::cout<< []()->int{return a>b;}()<<std::endl;
}
编译器提示错误:
[=] //以传值方式捕获作用域中的所有变量,但传递给lambda的值是常量,下面的例子揭示了这点
int main()
{
int a=10;
//尝试修改一个以值传递进行捕获的局部变量
std::cout<< [a](){a++;return a;}()<<std::endl; //这里的[a]后面会讲解;
}
编译器提示错误:
[&] //以传址方式捕获作用域中的所有变量,可以在lambda函数中修改传进去的值,且修改的值会影响原值,如下面的例子
int main()
{
int a=10;
//尝试修改一个以值传递进行捕获的局部变量
std::cout<< [&a](){a++;return a;}()<<std::endl; //这里的[&a]后面会讲解;
}
运行结果:
[x] //以传值的方式,只捕获x,无法在lambda函数中使用其他未捕获的变量
[&x] //以传址的方式,只捕获x,无法在lambda函数中使用其他未捕获的变量,如下面的代码是错误的。
int main()
{
int a=10;
int b=0;
//尝试使用一个未捕获的局部变量
std::cout<< [&a](){b=20;return b;}()<<std::endl;
}
编译器提示错误:
[=,&x] //除x以传址方式进行捕获,其他的局部变量以传值方式进行捕获。
[&,x] //除x以传值方式进行捕获,其他的局部变量以传址方式进行捕获。
也许有人会问,既然能传递参数,那还要这些捕获的变量做什么呢?
如下面这两个代码的返回结果是一样的
int main()
{
int a=10;
int b=15;
std::cout<< [a](int b){return a+b;}(b)<<std::endl; //传进一个参数b并捕获局部变量a
std::cout<<[](int a,int b){return a+b;}(a,b)<<std::endl; //传进参数a,b
}
的确,如果不考虑传进参数的个数,那么这两个的确是等价的,可是,考虑下如果只能传进一个参数,却要比较2个值呢?
如计算某个数组中值大于x的元素个数?
下面是一个例子
int main()
{
int a=4;
int arr[10]={1,2,3,4,5,6,7,8,9,10};
std::cout<<std::count_if(arr,arr+10,[a](int b)->bool{return b>a;})<<std::endl;
}
其中count_if每次只传给谓语函数一个值,如果你写的是前面那种需要传2个值的函数就行不通了。
(注:这样写并不是最好的,只是为了说明捕获变量的用途才写成那样的。下面的写法更简便(虽然lambda也是函数对象类。但我没办法把它写成一个局部变量都不用的形式)
#include<functional>
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
std::cout<<std::count_if(arr,arr+10,bind2nd(std::greater<int>(),4))<<std::endl;
}
)
使用lambda的好处
简洁性:你可以不用特意去定义一个只使用一次的函数。
方便性:如上面那个count_if的例子,你可以直接看到并修改函数体中的内容,如果不使用lambda函数,那你需要去定义一个函数,假设你的工程中有很多的函数,那你可能会浪费一点时间去查找你定义的那个函数。
文章写道这里就完鸟,受个人知识所限,如果错误,请留言指出。。