C++笔记之lambda表达式

引言
Lambda表达式是从C++ 11版本引入的特性,利用它可以很方便的定义匿名函数对象,通常作为回调函数来使用。大家会经常拿它和函数指针,函数符放在一起比较,很多场合下,它们三者都可以替换着用。
语法
[ captures ] ( params ) specs requires (optional) {body}
上面是完整的Lambda表达式结构,从左到右分别是:
- capture–捕获列表
- params–参数列表
- specification列表-- 可选部分,这块部分主要由变量说明符、异常、返回类型等组成
- requires – C++20 版本开始增加的
- body-- 函数体
关于specification和requires部分的详细描述可以参考:https://en.cppreference.com/w/cpp/language/lambda
我们平时的开发工作可能不会基于C++20版本,一般都是C++17及以下,所以就先记录一下,平时开发所接触的Lambda表达式。哪些新版本增加的相关特性就暂不讨论。
常见的Lambda表达式语法:

图片引自 微软C++课程
结构描述:
- 捕获列表,可以捕获外部变量
- 形参列表 (可选)
- 变量说明符(可选)属于specification列表,用来表示可以修改值捕获的变量,后面会详细说明
- exception (可选)属于specification列表,用来表示是否会有异常
- 返回类型 (可选)
- 函数体
从上面的结构描述,我们能看到,最简洁的lambda表达式应该是这样:
[]{}
我们常用的lambda表达式有以下几种:
[capture list]{body}
[capture list](params){body}
[capture list](params)->return type {body}
捕获列表
lambda表达式有两种捕获其作用域外部变量的方式,一种是值捕获,一种是引用捕获。
值捕获
#include <iostream>
using namespace std;
int main(int argc, char **argv) {int a = 100;auto test = [a]() mutable {a++;cout << "inside, a:" << a << endl;};test();cout << "outsize, a:" << a << endl;return 0;
}
输出结果:
inside, a:101
outsize, a:100
值捕获的情况下,如果需要某个特地的外部变量,那么直接在捕获列表里面写相应的变量名即可,如果想要值捕获所以外部变量,可使用如下形式:
[=]
上面的例子中有mutable,这个关键字的作用是运行lambda内部可以修改值捕获的变量,默认情况下,值捕获的变量是只读的。
引用捕获
#include <iostream>
using namespace std;
int main(int argc, char **argv) {int a = 100;auto test = [&a]() {a++;cout << "inside, a:" << a << endl;};test();cout << "outsize, a:" << a << endl;return 0;
}
输出结果:
inside, a:101
outsize, a:101
引用捕获外部变量的话,需要在变量名前加上**&,如果想要以引用捕获的方式访问所以外部变量,可以使用:[&]**
注意,这里我们移除了mutable关键字。
值捕获&引用捕获
因为是捕获列表嘛,所以当然可以互相组合搭配了,不然怎么能达到列表的定义呢。例如,我们想要以值捕获的方式捕获factor变量,以引用捕获的方式捕获total变量,那么可以用如下的方式:
[&total, factor]
[factor, &total]
[&, factor]
[=, &total]
以上面第一个方式举个例子:
#include <iostream>
using namespace std;
int main(int argc, char **argv) {int total = 100;float factor = 0.2f;auto test = [&total, factor]() mutable {factor = 0.5f;total = static_cast<int>(total * factor);cout << "inside, total:" << total << ", factor:" << factor << endl;};test();cout << "outsize, total:" << total << ",factor:" << factor << endl;return 0;
}
输出结果:
inside, total:50, factor:0.5
outsize, total:50,factor:0.2
在两种捕获方式互相搭配的使用过程中,需要注意一点的是,当捕获列表中已经使用了**&来捕获所以外部变量,就不能再使用&变量名**,捕获指定变量了,同理,值捕获也是这样。例如:
struct S { void f(int i); };void S::f(int i) {[&, i]{}; // OK[&, &i]{}; // ERROR: i preceded by & when & is the default[=, this]{}; // ERROR: this when = is the default[=, *this]{ }; // OK: captures this by value. See below.[i, i]{}; // ERROR: i repeated
}
注意
上面的例子中,访问外部的变量,都必须通过捕获列表“处理”一下,内部才能访问,其实还有一些情况是不需要捕获,lambda就能访问的。例如:
- 当lambda要访问的变量是全局的或者静态(static)的,可以直接使用
- Thread Local 变量
- constant expression 并且没有mutable成员 (只读)
- const修饰的non-volatile int型字面量 或者 由constant expression初始化的枚举类型 (只读)
下面举一些例子:
#include <iostream>
using namespace std;
int total = 100;
int main(int argc, char **argv) {static float factor = 0.2f;auto test = []() {factor = 0.5f;total = static_cast<int>(total * factor);cout << "inside,global total:" << total << ", static factor:" << factor<< endl;};test();cout << "outsize,global total:" << total << ", static factor:" << factor<< endl;return 0;
}
输出结果:
inside,global total:50, static factor:0.5
outsize,global total:50, static factor:0.5
#include <iostream>
#include <thread>
using namespace std;
int main(int argc, char **argv) {const int x = 1024;enum TYPE { kTypeApp = 0, kTypeUser };auto test = []() {cout << "type:" << kTypeUser << endl;cout << "x:" << x << endl;};test();return 0;
}
输出结果:
type:1
x:1024
参数列表&返回类型
lambda除了通过捕获列表的方式访问外部变量,也可以通过传递参数来与外界交流。跟普通函数没啥区别,这个没啥好说的。需要知道的是lambda支持它的参数也可以是lambda表示式。
返回类型跟普通函数差别也不大,同样需要注意的是,跟参数列表一样,也是支持返回lambda表达式的。同时,如果不指定返回类型的话,那么可以用auto关键字接收返回结果,自动推导结果。
#include <functional>
#include <iostream>
using namespace std;
int main() {auto addtwointegers = [](int x) -> function<int(int)> {return [=](int y) { return x + y; };};auto higherorder = [](const function<int(int)>& f, int z) {return f(z) * 2;};auto answer = higherorder(addtwointegers(7), 8);cout << answer << endl;
}
输出结果:
30
lambda嵌套
lambda表达式内部还可以创建lambda表达式,套娃的感觉🪆。
#include <iostream>
using namespace std;
int main()
{int ret = [](int x) { return [](int y) { return y * 2; }(x) + 3; }(5);cout << ret << endl;
}
输出结果:
13
参考
https://learn.microsoft.com/en-us/cpp/cpp/examples-of-lambda-expressions?view=msvc-170
https://en.cppreference.com/w/cpp/language/lambda
相关文章:
C++笔记之lambda表达式
引言 Lambda表达式是从C 11版本引入的特性,利用它可以很方便的定义匿名函数对象,通常作为回调函数来使用。大家会经常拿它和函数指针,函数符放在一起比较,很多场合下,它们三者都可以替换着用。 语法 [ captures ] (…...
flink大数据处理流式计算详解
flink大数据处理 文章目录flink大数据处理二、WebUI可视化界面(测试用)三、Flink部署3.1 JobManager3.2 TaskManager3.3 并行度的调整配置3.4 区分 TaskSolt和parallelism并行度配置四、Source Operator(资源算子)五、Sink Operator(输出算子)六、Flink滑…...
Java面试题(二十三)DCL单例
懒汉式单例 private static SingletonInstance INSTANCE;private SingletonInstance(){}public static SingletonInstance getInstance() {if (INSTANCE null) {INSTANCE new SingletonInstance();}return INSTANCE;}构造方法私有化,然后判断是否为空,…...
UML-类图
一、类 一个类由三个格子组成,从上至下分别表示: 第一格:类名称(接口和抽象类,使用斜体) 第二格:类的属性(成员变量,可以没有) 第三格:类的操作&…...
PostgreSQL 数据库和 pgAdmin 4
PostgreSQL 数据库和 pgAdmin 4PostgreSQLPostgreSQL 数据库安装PostgreSQL 数据库安装 (Ubuntu)PostgreSQL 数据库其他系统安装PostgreSQL 数据库快速使用入门登录数据库访问数据库参考pgAdmin 4pgAdmin 4 安装使用 pgAdmin 4 登录数据库参考PostgreSQL PostgreSQL 数据库安装…...
quarkus 搭建与基础开发环境配置总结
quarkus搭建与基础开发环境配置总结 大纲 基础概念quarkus2.13.7脚手架工程配置配置maven3.8.7quarkus快速启动quarkus的三种打包方式quarkus将程序打包为二进制文件window环境下quarkus云原生二进制文件打包环境搭建使用GraalVM-java11替换本地java8运行二进制文件 基础概念…...
扩散模型DDPM开源代码的剖析【对应公式与作者给的开源项目,diffusion model】
扩散模型DDPM开源代码的剖析【对应公式与作者给的开源项目,diffusion model】一、简介二、扩散过程:输入是x_0和时刻num_steps,输出是x_t三、逆扩散过程:输入x_t,不断采样最终输出x_0四、具体参考算法流程图五、模型mo…...
C语言 学生记录管理系统
学生记录管理系统 1--添加 2--删除 3--查询:按姓名 4--查询:按班级 5--查询:按学号 0--退出 请选择操作序号(0—5):1 请输入新学生的学号:1 请输入新学生的…...
【独家】华为OD机试 C 语言解题 - 交换字符
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...
网络安全平台测试赛 easyphp(phar脏数据处理)
昨天的比赛,14.00-17.00.时间有点紧张,比赛期间没拿下来这道 😭非常痛苦,很顺畅的思路 一步步想下来,卡在最后一步末尾脏数据处理了,最后时间到了 没打通,还需多练 这里本地复现一下࿱…...
【python】XML格式文件读写详解
注:最后有面试挑战,看看自己掌握了吗 文章目录XML介绍格式XML与AJAX与HTML区别联系生成XML文件案例用SAX模块处理XML用DOM模块处理XML🌸I could be bounded in a nutshell and count myself a king of infinite space. 特别鸣谢:…...
理解js的精度问题
参考博客:js精度丢失问题-看这篇文章就够了(通俗易懂)、探寻 JavaScript 精度问题以及解决方案、JavaScript 浮点数陷阱及解法 1 为什么 JavaScript 中所有数字包括整数和小数都只有一种类型 即 Number类型,它的实现遵循 IEEE 754 标准。 符号位S&#…...
蓝桥杯 时间显示
题目 输入输出样例 示例 1 输入 46800999输出 13:00:00示例 2 输入 1618708103123输出 01:08:23评测用例规模与约定 对于所有评测用例,给定的时间为不超过 10^{18}1018 的正整数。 运行限制 最大运行时间:1s最大运行内存: 512M 基础知识 时间的转换…...
qt中设置菜单高度
如题所示,我建立一个菜单,代码如下,但是菜单项的高度太小了, { popupMenu new QMenu(this); QAction *action1 new QAction(tr(“&New1”), this); QAction *action2 new QAction(tr(“&New2”), this); QA…...
测开:前端基础-css页面布局-定位
一 、传统网页布局的三种方式 网页布局的本质–用CSS来摆放盒子,把盒子摆放到相应的位置,css提供了三种传统布局方式,分别是标准流,浮动和定位三种。 二、 定位 2.1 啥是定位 我的理解,就是要把这个元素,…...
Servlet中八个监听器介绍
一、监听对象创建的监听器 1、ServletContextListener /*** 用于监听ServletContext对象创建和销毁的监听器* since v 2.3*/public interface ServletContextListener extends EventListener {/*** 对象创建时执行此方法。该方法的参数是ServletContextEvent事件对象…...
LicenseBox Crack,对服务器的要求最低
LicenseBox Crack,对服务器的要求最低 LicenseBox是用于管理基于PHP的软件、WordPress插件或主题、主题、插件和WordPress的更新和许可的完整软件。它易于安装,对服务器的要求最低,用户友好的界面,无限脚本的使用为您的创造力打开了大门。 Li…...
css中重难点整理(vertical-align)
一、vertical-align 在学习vertical-align的时候,可能会很困惑。即使网上有一大推文章讲veitical-align,感觉看完好像懂了,等自己布局的时候用到vertical-align的时候好像对它又很陌生。这就是我在布局的时候遇到的问题。 本来vertical-align就很不好理…...
javaScript基础面试题 ---宏任务微任务
宏任务微任务一、为什么JS是单线程语言?二、JS是单线程,怎样执行异步代码?1、JS是单线程语言 2、JS代码执行流程,同步执行完,再进行事件循环(微任务、宏任务) 3、清空所有的微任务,再…...
基于JSP的网上书城
技术:Java、JSP等摘要:随着科技的迅速发展,计算机技术已应用到社会的各个领域。随着计算机技术和通信技术的迅速发展,网络的规模也逐渐增大,网络的元素也随之不断增加,有的利用其通信,有的利用其…...
springboot+vue基于web的校园失物招领系统的设计系统
目录同行可拿货,招校园代理 ,本人源头供货商系统功能模块分析交互与流程设计技术实现要点项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作同行可拿货,招校园代理 ,本人源头供货商 系统功能模块分析 用户模块 注册与登录&…...
别再单独部署Mosquitto了!用Docker一步搞定带MQTT插件的RabbitMQ 3.13
告别繁琐部署:用Docker Compose快速搭建支持MQTT的RabbitMQ集群 在物联网和微服务混合架构中,消息中间件选型常常让开发者陷入两难——选择轻量级的Mosquitto MQTT broker虽然能满足设备通信需求,却无法处理服务间的AMQP消息;部署…...
如何用开源工具实现3D打印钥匙自由?从参数测量到模型生成的实践路径
如何用开源工具实现3D打印钥匙自由?从参数测量到模型生成的实践路径 【免费下载链接】keygen OpenSCAD tools for generating physical keys 项目地址: https://gitcode.com/gh_mirrors/ke/keygen 在数字化制造蓬勃发展的今天,3D打印技术正逐步走…...
除了阿里云,还有哪些靠谱的身份证实名认证方案?SpringBoot整合横向评测
SpringBoot整合主流身份证实名认证API横向评测:从阿里云到多服务商技术选型指南 当你的应用需要接入身份证实名认证功能时,阿里云可能只是众多选项中的一个起点。作为技术决策者,如何在腾讯云、百度智能云、聚合数据等众多服务商中做出最优选…...
如何通过技术优化提升Element Plus开发效率
如何通过技术优化提升Element Plus开发效率 【免费下载链接】element-plus 🎉 A Vue.js 3 UI Library made by Element team 项目地址: https://gitcode.com/GitHub_Trending/el/element-plus 在前端开发过程中,Element Plus作为一款基于Vue.js 3…...
GLM-4.1V-9B-Base与MATLAB联动:科学计算可视化报告的自动生成
GLM-4.1V-9B-Base与MATLAB联动:科学计算可视化报告的自动生成 1. 科研工作流中的痛点与解决方案 科研人员每天都要面对大量实验数据,从原始数据到最终的可视化报告往往需要经历繁琐的步骤。传统的数据分析流程通常包括:数据整理→MATLAB编程…...
PFC(5.0)模拟:GBM模型(grain- based model ) pb-sj或pb-...
PFC(5.0)模拟:GBM模型(grain- based model ) pb-sj或pb-pb 单轴压缩。 模拟花岗岩等矿物晶体岩石,多种矿物晶体模型,其中矿物种类 数量分布可以自定义。 可以监测sj裂纹,和各矿物内裂纹。PFC5.0的GBM模型玩岩石破裂是真…...
DeerFlow2.0 Docker + 本地 Ollama qwen3.5:9b 部署指南
DeerFlow2.0 Docker 本地 Ollama qwen3.5:9b 部署指南 实现 Token 自由!!!本地模型免费 :) 1. 前提条件 Windows 11 家庭版(版本号 25H2)Docker Desktop 已安装并运行WSL2 已安装并配置Olla…...
小觅相机‘凉了’之后,我们如何用它的SDK和开源工具链构建自己的SLAM数据集?
从废弃硬件到研究利器:小觅相机SDK与开源工具链的SLAM数据集构建指南 当一款硬件产品的厂商突然消失,官网关闭、技术支持中断,那些被遗弃的设备往往会被贴上"电子垃圾"的标签。但作为一名SLAM研究者或爱好者,你是否想过…...
SDMatte效果对比评测:与传统抠图工具及在线API的全面比拼
SDMatte效果对比评测:与传统抠图工具及在线API的全面比拼 1. 开篇:为什么需要新的抠图方案 在数字内容创作领域,抠图一直是个让人又爱又恨的技术活。记得去年帮朋友做电商产品图,光是给20个商品抠图就花了我整整一个周末。传统工…...
