浅出匿名函数lambda

跟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函数,那你需要去定义一个函数,假设你的工程中有很多的函数,那你可能会浪费一点时间去查找你定义的那个函数。



大笑大笑文章写道这里就完鸟,受个人知识所限,如果错误,请留言指出。。害羞害羞


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值