【C++】【lambda】lambda函数介绍和个人理解(1)——初识lambda

导航:


lambda函数介绍和个人理解(1)——初识lambda

lambda函数介绍和个人理解(2)——lambda与仿函数

lambda函数介绍和个人理解(3)——lambda的语法甜点

什么是lambda函数?

其实,lambda函数我个人更愿意称为lambda运算(lambdacalculus),它是用来表示一种匿名函数。这个严格意义上属于“函数式编程”(Functional
Programming)的范畴。当然还是先解释下函数式编程的概念的好。按照当时冯·诺依曼机器的基本计算模型,所谓通过一条条机器指令逐步把输入数据加工成最终的计算结果,而在计算过程中会有大量的内存单元被反复修改。函数式编程的思想就是把所有的这些状态看做一个全集,程序的基本组成部分就是这些状态之间的映射,其实也就是广义上的函数(广义上的函数的概念是,只要存在广义上的集合A,B,并且存在从A映射到B的映射关系,这个映射关系就被称作广义上的函数。在计算机编程领域,广义的函数包含过程,也就是Pascal语言中有名的Procedure)。通过这些函数之间的复杂运算,把输入数据映射到最终结果,这就是函数式编程。回到一开始的lambda运算,lambda运算其实我们就可以理解成一个简单的运算方法,就像加法减法乘法除法一样,就是一个运算规则:

lambda运算 := 传入数据 –>一系列的运算 -> 传出结果

这就是神龙见首不见尾的lambda运算。他其实就是一个运算规则,说的高雅点,叫做lambda算子(lambda
operator)。这时候,如果我们结合理解函数式编程的理念,我们就知道为什么这个东西叫lambda函数了,因为满足我上文中所讲到的广义函数的定义啊!广义集合A(传入数据)和广义集合B(传出数据)还有他们的映射关系(一系列的运算),所以其实这个运算就是一个函数。至此,我们终于了解了为什么叫lambda函数。

“匿名的”?匿名的!


可是为什么又要提到,lambda函数是一个匿名函数呢?什么叫“匿名的”函数呢?一般而言,我们都知道,所谓的函数,不论是哪一种编程语言,都要给自定义的函数进行命名处理,看似天经地义。然而只有一种例外,那便是lambda函数。lambda函数没有名字,对的,没有函数名。你可能要问:不对啊?你刚刚不是说,这个lambda函数满足上述的广义函数定义,他不就是一个函数么?

其实这个问题不难解决。没错,他是函数,但没有任何人规定:“一个函数,必须有一个名字与其对应。”你肯定会说,呵呵!你又跟我玩文字游戏。那你解释下lambda函数他究竟是个什么?OK!交给我了:

先给大家看几个典型的lambda函数使用的例子:


/****
*@PoloShen
*Title: lambda 01
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main(){
auto total = [](int a, int b)->int{return a+b; }; //生成一个lambda函数,求两数之和
cout<<total(3,5)<<endl; //输出8, 3+5=8
vector<int> nums;
for (int i = 0; i < 5; i++) nums.push_back(i); //将nums初始化
auto print = [&]{ //生成一个lambda函数,用于打印nums
for (auto s: nums){cout<<s<<"\t";}
cout<<endl;
};
print(); //打印nums
for_each(nums.begin(), nums.end(), [=](int &i){ //将nums每一个元素加10
i += 10;
});
print(); //再次打印nums
return 0;
}
//编译选项:: g++ -std=c++11 lambda01.cpp

对我们这些程序员而言,lambda函数是一个“不定态事物”,它既可以写成一个类似变量的形式,又可以写在函数指针的接口上,还可以当做一个类似于“局部函数”的东西使用。但实际上,从最简单易懂的地方去理解,lambda函数只会出现在两个地方:变量等号后面,还有函数指针的接口上。例子1中,变量total和变量print后面就分别接了一个lambda函数,分别用于计算两数之和和打印数表;另外一个就是在for_each方法中的那个lambda函数,用于使数表中的元素值增加10。看上去,total、print就像他们的函数名一样,但实际上则不然。严格意义上,他们依然是变量,只不过这个类型很复杂;但是实际上,他们就是一个“传令兵”,只是在引用中免得你找不到而已。更多情况下,按照所谓的函数式编程的理念,“万物皆函数”(笑),lambda函数更多的应当出现在最需要他的地方,也就是有函数指针的地方。所以不必在意他是什么名字,只需要考虑如何好好地完成任务即可。就比方说我们看到的在for_each中所使用的lambda函数一样,不用关心他的名字是什么,我们关心的是实现这个运算的方法。如此一来就不难理解lambda函数的匿名性了。

至此,最难啃的两块骨头已经被我们吃下去了,剩下的就是慢慢消化。

lambda函数的语法定义


lambda函数的语法定义如下:

[capture](parameters) mutable -> return-type{statsment}

其中

  • [capture]捕捉列表。捕捉列表总是出现在lambda函数的开始处。事实上,[]是lambda函数的引出符。编译器根据该引出符判断接下来的代码是否是lambda函数。捕捉列表能够捕捉上下文中的变量以供lambda函数使用。

  • (parameters)参数列表。其实就是和普通额函数参数列表一致。如果不需要参数传递,则可以连同括号一起省略。

  • mutablemutable修饰符。默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。在使用该修饰符时,参数列表不可省略,即使参数为空。

  • ->return-type返回类型。同追踪返回类型形式声明函数的返回类型。出于方便,不需要返回值的时候也可以连同符号->一起省略。此外,在返回类型明确的情况下,也可以省略该部分,让编译器自行对返回类型进行推导。

  • {statsment}函数体。内容与普通函数一样,不过除了可以使用的参数之外,还可以使用所有捕获的变量。

以上便是lambda函数的定义了。和其他常规的函数不同,lambda函数可以去使用通过捕获列表中的数据。语法上,捕获列表有多个捕捉项组成,并以逗号分隔。以下便是捕获列表的形式:

  • [var]表示值传递方式捕获变量var

  • [=]表示值传递方式捕获所有父作用域的变量(包括this)

  • [&var]表示引用传递方式捕获变量var

  • [&]表示引用传递方式捕获所有父作用域的变量(包括this)

  • [this]表示值传递方式捕获当前的this指针

但是请注意!捕获列表不允许变量的重复传递。比如说:

  • [=, a] 重复捕获a,错误。

  • [&, &this] 重复捕获this,错误

Ok,到这里,所有语法上的lambda函数说明都完成了,给一些简单的例子,然后慢慢畅游吧!


/****
*@PoloShen
*Title: lambda 02
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
int main(){
[]{}; //最简lambda函数
int a = 3, b = 4;
[=]{return a+b;}; //省略参数列表和返回类型
auto fun1 = [&](int c){b = a + c;}; //省略了返回类型,无返回值
auto fun2 = [=, &b](int c)->int{return b += a + c;};//各部分都很完整的lambda函数
auto fun3 = [a, &b]()->int{return a+b;}; //其他传递方式的例子
return 0;
}
//编译选项:: g++ -std=c++11 lambda02.cpp

时间: 2024-11-05 21:46:56

【C++】【lambda】lambda函数介绍和个人理解(1)——初识lambda的相关文章

【C++】【lambda】lambda函数介绍和个人理解(3)——lambda的语法甜点

导航: lambda函数介绍和个人理解(1)--初识lambda lambda函数介绍和个人理解(2)--lambda与仿函数 lambda函数介绍和个人理解(3)--lambda的语法甜点 其实,与其说这是一篇介绍lambda语法甜点的文章,不如说是一篇教大家使用lambda函数的一篇文章.当然不可避免的会用到一些有趣的实验.文章略长,大家耐心耐心看吧!当然,这也是本人写的关于lambda函数的最后一篇博文了,如果大家有其他更好的想法或者更深入的理解,请联系我~ 本文大概讲这些内容:基础使用,

【C++】【lambda】lambda函数介绍和个人理解(2)——lambda与仿函数

前言: 本来是打算11月末的时候写这篇文章,结果一直拖拖拖拖拖啊啊啊啊啊事多啊事多!OK这是对lambda的分析的第二篇,第三篇准备给大家带来一些"语法甜点",不过实在是不知道什么时候能够写完=.=到时候再说 导航: lambda函数介绍和个人理解(1)--初识lambda lambda函数介绍和个人理解(2)--lambda与仿函数 lambda函数介绍和个人理解(3)--lambda的语法甜点 正文: 好点的编程语言一般都有好的库支持,C++也不例外.C++语言在标准程序库STL中

【C++】lambda函数介绍和个人理解

一般数据类型的别名 众所周知,在C++中,有一种不同于地址引用的值引用类型,也就是这种定义. int a = 10; cout << a << endl;//:10 int& d = a;//d为a的别名 cout << d << endl;//:10 a++; cout << a << endl;//:11 d++; cout << a << endl;//:12 cout << d &l

深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

转:http://zh.lucida.me/blog/java-8-lambdas-inside-out-library-features/ 关于 深入理解 Java 8 Lambda(语言篇--lambda,方法引用,目标类型和默认方法) 深入理解 Java 8 Lambda(类库篇--Streams API,Collector 和并行) 深入理解 Java 8 Lambda(原理篇--Java 编译器如何处理 lambda) 本文是深入理解 Java 8 Lambda 系列的第二篇,主要介绍

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

最近看了一下java 8的一些新特性,其中最重要的莫过于Lambda表达式了,通过一阵子的学习,原本准备自己写一篇博客的,后来阅读了一位学长翻译过来的博客(原文是Brain Goetz的State of Lambda,下面会给出原文链接),觉得写的十分完美,把我想要写的和我没想到的都罗列了出来,就把这个分享给大家了. 注:原译文见  http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 英语原版见:http://cr.

[转]深入理解Java 8 Lambda(类库篇——Streams API,Collectors和并行)

以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-library-features 本文谢绝转载,如需转载需征得作者本人同意,谢谢. -------------------------------------内容分割线--------------------------------------------------------- 深入理解Java

[转]深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

以下内容转自: 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features 本文谢绝转载,如需转载需征得作者本人同意,谢谢. -------------------------------------内容分割线--------------------------------------------------------- 关于 本文是深入

[转载]深入理解Java 8 Lambda

原文链接:http://zh.lucida.me/blog/java-8-lambdas-insideout-language-features/ 深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法) 2014年10月24日 | 评论 作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 关于 深入理

Python的lambda匿名函数

lambda函数也叫匿名函数,即,函数没有具体的名称.先来看一个最简单例子: def f(x):return x**2print f(4) Python中使用lambda的话,写成这样 g = lambda x : x**2print g(4) lambda表达式在很多编程语言都有对应的实现.比如C#: var g = x => x**2Console.WriteLine(g(4)) 那么,lambda表达式有什么用处呢?很多人提出了质疑,lambda和普通的函数相比,就是省去了函数名称而已,同