C++补充部分(一)--lambda 表达式

lambda 表达式

lambda 表达式本质是一个匿名函数对象,跟普通函数不同的是他可以定义在函数内部。 lambda 表达式语法使用层面而言没有类型,所以我们一般是用 auto 或者模板参数定义的对象去接收 lambda 对象。

lambda 表达式的格式:[capture-list] (parameters)-> return type { function body }

当然对于某些部分没有参数传入或者返回的情况是可以进行省略的

**[capture-list]:**捕捉列表,该列表总是出现在 lambda 函数的开始位置,编译器根据[]来判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上下文中的变量供 lambda 函数使用,捕捉列表可以传值和传引用捕捉,具体细节 7.2 中我们再细讲。捕捉列表为空也不能省略。

(parameters): 参数列表,与普通函数的参数列表功能类似,如果不需要参数传递,则可以连同()一起省略。

**->return type:**返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。一般返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。

**{function body}:**函数体,函数体内的实现跟普通函数完全类似,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量,函数体为空也不能省略。


实际应用

仿函数

想要根据不同的筛选条件来给数据进行排序,我们之前往往采用的仿函数的形式

想要用多种的不同比较逻辑就要写多种仿函数

lambda 表达式

相对于仿函数,这个写起来更加的简便明了

仿函数 vs lambda 表达式

mbda 表达式本质是编译器自动生成的匿名仿函数。我们手写仿函数需要自己定义类,而 lambda 是语法糖,编译器在底层自动帮我们生成匿名类并重载operator()。

手写仿函数需要显式定义类或结构体,可以复用,能够在多处创建对象,支持在类内定义多个成员变量保存状态,代码篇幅更长。

lambda 表达式不需要手动定义类,写法简洁轻便,一般用于临时场景,比如 STL 算法传参,捕获列表用来获取外部变量,只能在定义位置使用,无法复用。

捕获列表

Lambda 表达式中默认只能用 lambda 函数体和参数中的变量,如果想用外层作用域中的变量就需要进行捕捉

第一种捕捉方式是在捕捉列表中显示的传值捕捉和传引用捕捉,捕捉的多个变量用逗号分割。x,y,\&z 表示 x 和 y 值捕捉,z 引用捕捉。

第二种捕捉方式是在捕捉列表中隐式捕捉,我们在捕捉列表写一个 = 表示隐式值捕捉,在捕捉列表写一个 & 表示隐式引用捕捉,这样我们 lambda 表达式中用了那些变量,编译器就会自动捕捉那些变量。

第三种捕捉方式是在捕捉列表中混合使用隐式捕捉和显示捕捉。=, \&x 表示其他变量隐式值捕捉,x 引用捕捉;\&, x,y 表示其他变量引用捕捉,x 和 y 值捕捉。当使用混合捕捉时,第一个元素必须是 & 或 =,并且 & 混合捕捉时,后面的捕捉变量必须是值捕捉,同理 = 混合捕捉时,后面的捕捉变量必须是引用捕捉。

如果对c的值进行修改也是不行的

将捕获的位置进行交换也是不行的

混合的捕捉方法都是要求**&,=**在最前面

Lambda 表达式如果在函数局部域中,他可以捕捉 lambda 位置之前定义的变量,不能捕捉静态局部变量和全局变量,静态局部变量和全局变量也不需要捕捉,lambda 表达式中可以直接使用。这也意味着 lambda 表达式如果定义在全局位置,捕捉列表必须为空。

因该直接不用捕获

  • 普通局部变量:必须捕捉;传值捕捉 mutable 只能改副本;引用捕捉才改原值
  • static 局部变量 / 全局变量:不需要捕捉,直接读写,修改就是改原值

传值捕捉 mutable 只能改副本,外层的a和b都是原来的值

lambda 的原理

Lambda 和范围 for 循环有相似之处,编译到汇编指令层面时,语言层面并不存在 lambda、范围 for 这种特殊语法。范围 for 底层依靠迭代器实现,而 lambda 底层本质是仿函数对象。

当我们书写一段 lambda 表达式后,编译器会自动生成一个对应的仿函数类。

这个自动生成的仿函数类,类名由编译器按照特定规则生成,保证每一个 lambda 生成的类名互不重复。 lambda 的参数、返回类型、函数体,会直接作为仿函数中operator()重载函数的参数、返回类型与函数体。 lambda 捕捉列表里的变量,本质就是这个仿函数类的成员变量。捕捉列表中的变量,会作为实参传入这个仿函数类的构造函数。如果使用隐式捕捉,编译器会分析 lambda 内部实际用到了哪些变量,只传递被使用到的对象。

相关推荐
Pniubi3 小时前
HashMap的扩容和树化边界
java·开发语言
gCode Teacher 格码致知5 小时前
Pandas教学-17:Series与Dataframe的关系
开发语言·python·pandas
发量惊人的中年网工5 小时前
分公司访问总部ERP慢怎么办?SD-WAN组网的排查与验收要点
服务器·开发语言·php
下页、再停留5 小时前
【C#桌面客户端系列学习-15】生成可视化图表之折线图、柱状图、饼状图
开发语言·c#
ShineWinsu6 小时前
对于JavaScript:操作元素的解析
开发语言·前端·javascript·面试·web·dom·元素
益莱储中国7 小时前
深度解析:RF 实验室从 5G迈向 6G 的过程中保持技术领先与设备升级的路径
开发语言·php
丰色木夕8 小时前
Ubuntu22.04下源码编译安装USD-Brep
c++·ubuntu·nvidia·usd-brep
benchmark_cc8 小时前
Python 量化系统如何设计统一的数据访问接口:从策略解耦到数据层架构
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
const_qiu8 小时前
第四章 00:开篇 —— 从「会聊天」到「记得住、会干活、能协作」
java·开发语言·人工智能·python