【C++】简单介绍lambda表达式

在这里插入图片描述
各位大佬好,我是落羽!一个坚持不断学习进步的学生。
如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步!

也欢迎关注我的blog主页: 落羽的落羽

文章目录

  • 一、 什么是lambda表达式
  • 二、 表达式语法
  • 三、lambda的应用

一、 什么是lambda表达式

C++中有“可调用对象”的概念,主要包括函数指针、仿函数、lambda表达式。lambda表达式本质是一个匿名函数对象,跟普通函数不同的是,他可以定义在函数内部

lambda表达式在语法使用层面上“没有类型”,简单来说:lambda表达式的类型是编译器即时生成的、唯一的、匿名的,程序员无法在代码中直接写出它的类型名称。lambda表达式使用时本质是被转换成一个仿函数再使用的,每个lambda表达式都会被编译器转换成一个独一无二的、匿名的类(仿函数)。即使两个lambda看起来完全一样,编译器也会为它们生成两个不同的类。所以,我们一般都是用auto或者模板参数定义的对象去接收lambda对象

二、 表达式语法

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

  • (parameters):参数列表。与普通的函数参数列表功能类似,如果不需要传参,则可以连同()一起省略。
  • ->return-type:return type是lambda函数的返回值类型。如果没有返回值,那么->return type这部分就可以省略,或者返回值类型明确的情况下,能由编译器自动推导返回类型出来,也能省略这部分。
  • {function body}:函数体。函数体的实现与普通函数完全一样,函数体内除了能使用参数列表外,还可以使用捕捉列表内的变量。函数体为空也必须写{}
  • [capture-list]:捕捉列表。该列表写在lambda表达式的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数。捕捉列表能够捕捉上下文的变量,以供lambda函数内部使用,捕捉列表可以传值或传引用,捕捉列表就算为空也必须写[]

举几个栗子:

auto add = [](int x, int y){ return x + y; };

在这里插入图片描述

auto func = []{cout << "hello world" << endl;};

在这里插入图片描述

auto swap = [](int& a, int& b){int tmp = a;a = b;b = tmp;};

在这里插入图片描述
非常好理解吧!

关于捕捉列表,还有一些使用的细节:

lambda表达式中默认只能使用参数列表中的变量或lambda内定义的,如果想使用外层作用域中的变量就需要进行捕捉。

  • 第一种方式是显式捕捉,在捕捉列表中可以显式传值捕捉和传引用捕捉,捕捉的多个变量用逗号分隔,比如[x, y, &z]表示x和y进行传值捕捉,lambda内部改变x和y不会改变原变量,而z是传引用捕捉,对z的改变会改变原变量。
  • 第二种捕捉方式是隐式捕捉,我们在[ ]中写一个 = 表示隐式值捕捉,写一个 & 表示隐式引用捕捉。这样我们的lambda的表达式中使用了哪些外部变量,编译器就会自动捕捉那些变量。
  • 第三种捕捉列表是混合捕获,可以组合使用隐式捕获和显式捕获,实现更精细的控制。[=, &x] 表示x进行引用捕捉,其余变量都为值捕捉;[&, x, y] 表示x和y进行值捕捉,其余变量进行引用捕捉。使用混合捕捉时,第一个元素必须是=或&,第一个是=时,后面的捕捉变量必须是引用捕捉;第一个是&时,后面的捕捉变量必须是值捕捉。

lambda表达式中如果在局部域时,可以捕捉到它之前定义的变量,不能捕捉静态局部变量和全局变量,因为这两种变量本来就不需要捕捉也能在内部直接使用,lambda表达式内部可以直接使用。lambda表达式如果定义在全局位置,捕捉列表必须为空。

默认情况下,lambda捕捉列表是const属性的,也就是说传值捕捉来的对象不能被修改,在参数列表后加上修饰符mutable就可以取消其常性,但是修改还是改变的形参对象,不会影响实参。使用该修饰符后参数列表不能省略。

int x = 0;
// 捕捉列表必须为空,因为全局变量不⽤捕捉就可以⽤,没有可被捕捉的变量
auto func1 = [](){x++;};int main()
{// 只能⽤当前lambda局部域和捕捉的对象和全局对象int a = 0, b = 1, c = 2, d = 3;auto func1 = [a, &b]{// 值捕捉的变量不能修改,引⽤捕捉的变量可以修改//a++;b++;int ret = a + b;return ret;};cout << func1() << endl;// 隐式值捕捉// ⽤了哪些变量就捕捉哪些变量auto func2 = [=]{int ret = a + b + c;return ret;};cout << func2() << endl;// 隐式引⽤捕捉// ⽤了哪些变量就捕捉哪些变量auto func3 = [&]{a++;c++;d++;};func3();cout << a << " " << b << " " << c << " " << d << endl;// 混合捕捉1auto func4 = [&, a, b]{//a++;//b++;c++;d++;return a + b + c + d;};func4();cout << a << " " << b << " " << c << " " << d << endl;// 混合捕捉1auto func5 = [=, &a, &b]{a++;b++;/*c++;d++;*/return a + b + c + d;};func5();cout << a << " " << b << " " << c << " " << d << endl;// 局部的静态和全局变量不能捕捉,也不需要捕捉static int m = 0;auto func6 = []{int ret = x + m;return ret;};// 传值捕捉本质是⼀种拷⻉,并且被const修饰了// mutable相当于去掉const属性,可以修改了// 但是修改了不会影响外⾯被捕捉的值,因为是⼀种拷⻉auto func7 = [=]()mutable{a++;b++;c++;d++;return a + b + c + d;};cout << func7() << endl;cout << a << " " << b << " " << c << " " << d << endl;return 0;
}

三、lambda的应用

学习lambda表达式之前,我们使用的可调用对象只有函数指针和仿函数,它们的定义都相对麻烦,使用lambda表达式去定义可调用对象,就十分简单方便了。

vector<pair<int, int>> v = { {1,2}, {3,4}, {8,3}, {5,1} };
//遇到这样的场景,假如我们想要用多种排序规则进行排序,以前是需要写不同的仿函数传给sort/*struct Compare_first
{bool operator()(const pair<int, int>& p1, const pair<int, int>& p2){return p1.first < p2.first;}
}; 
struct Compare_second
{bool operator()(const pair<int, int>& p1, const pair<int, int>& p2){return p1.second < p2.second;}
};
sort(v.begin(), v.end(), Compare_first());
sort(v.begin(), v.end(), Compare_second());*///有了lambda表达式后,就方便许多了
sort(v.begin(), v.end(), [](const pair<int, int>& p1, const pair<int, int>& p2) {return p1.first < p2.first; });
for (auto pa : v)
{cout << pa.first << ":" << pa.second << " ";
}
cout << endl;sort(v.begin(), v.end(), [](const pair<int, int>& p1, const pair<int, int>& p2) {return p1.second < p2.second; });
for (auto pa : v)
{cout << pa.first << ":" << pa.second << " ";
}
cout << endl;

在这里插入图片描述

本篇完,感谢阅读。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96016.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

磁共振成像原理(理论)4:自由进动和弛豫 (Free Precession and Relaxation)

当磁化自旋系统被射频脉冲扰动而偏离其热平衡态后&#xff0c;一旦移除外部激励并给予足够时间&#xff0c;系统将根据热力学定律返回平衡态。这一过程包含三个特征现象&#xff1a; (a) 自由进动——宏观磁化矢量 (M⃗\vec{M}M) 绕( B0⃗\vec {B_0}B0​​ )场的进动&#xff1…

ubuntu 20.04 安装spark

安装openjdk21 下载 wget https://download.java.net/openjdk/jdk21/ri/openjdk-2135_linux-x64_bin.tar.gz解压 tar -xvf openjdk-2135_linux-x64_bin.tar.gzsudo mv jdk-21/ /opt/jdk-21/设置环境变量 echo export JAVA_HOME/opt/jdk-21 | sudo tee /etc/profile.d/java2…

第三方区块链应用测评:【多签钱包合约安全评估_阈值签名机制与私钥存储安全性测试】

阈值签名机制安全测试密码学审计 采用门限签名方案&#xff08;TSS&#xff09;的多签钱包需验证其阈值BLS签名或ECDSA签名算法的正确性。测试重点包括&#xff1a;分布式密钥生成&#xff08;DKG&#xff09;过程的保密性&#xff08;无密钥信息泄露&#xff09;、签名碎片验证…

大模型处理长文档的挑战和解决方案?

当前&#xff0c;AI 应用正处于极速发展阶段&#xff0c;大语言模型&#xff08;LLM&#xff09;与检索增强生成&#xff08;RAG&#xff09;系统已成为构建智能问答、知识管理等高阶 AI 应用的核心引擎&#xff0c;被广泛应用于金融分析、学术研究、企业合规等多个领域。然而&…

JavaWeb--day1--HTMLCSS

(以下内容全部来自上述课程及课件) web开发介绍 1. 什么是web&#xff1f; Web&#xff1a;全球广域网&#xff0c;也称为万维网&#xff0c;能够通过浏览器访问的网站。 2. Web网站的工作流程 3. Web标准 Web标准也称为网页标准&#xff0c;由一系列的标准组成&#xf…

OpenEuler安装gitlab,部署gitlab-runner

目录 一、安装gitlab 二、安装部署docker设置源 三、下载部署runner ​编辑 四、构建CI/CD 一、安装gitlab 1.查看OpenEuler版本 [rootlocalhost ~]# cat /etc/os-release NAME"openEuler" VERSION"24.03 (LTS-SP1)" ID"openEuler" VERSI…

实战项目-----在图片 hua.png 中,用红色画出花的外部轮廓,用绿色画出其简化轮廓(ε=周长×0.005),并在同一窗口显示

实战项目实现以下功能&#xff1a;对图片 hua.png 进行轮廓提取&#xff0c;并在同一窗口中完成以下两个绘制操作&#xff1a;用红色画出花的外部轮廓&#xff08;即最外层轮廓&#xff09;用绿色画出该轮廓的近似多边形&#xff0c;其中近似精度参数 ε 设置为轮廓周长的 0.00…

开源鸿蒙北向框架开发:系统服务理论详解

系统服务的启动 基本可以认为&#xff1a;OpenHarmony 的系统服务进程都是“由 init 直接或间接拉起”的。 直接方式&#xff1a; init 按 /system/etc/init/.cfg 启动可执行&#xff08;如 /system/bin/sa_main、/system/bin/samgr 等&#xff09;&#xff0c;这些进程的 PPid…

龙虎榜——20250909

上证指数今天缩量收阴线&#xff0c;跌破10日均线&#xff0c;目前日线总体处于高位宽幅震荡中&#xff0c;小级别暂未明确方向&#xff0c;指数面临方向选择&#xff0c;需要注意高位股的风险。 深证指数今天缩量收阴线&#xff0c;跌破5日均线&#xff0c;接下来几天方向的选…

基于dijkstra算法的WSN网络MAC协议matlab仿真,分析网络延迟与网络开销

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.部分程序 4.算法理论概述 5.完整程序 1.程序功能描述 无线传感器网络&#xff08;WSN, Wireless Sensor Network&#xff09;是由大量低成本、低功耗的传感器节点组成&#xff0c;通过无线通信实现数据采集、传输与…

ES数据库启动时可以设置1G一下内存吗

可以&#xff0c;但强烈不建议在生产环境中这样做。ES 7.0 版本确实可以设置小于 1GB 的堆内存&#xff0c;但这会带来严重的性能问题和稳定性风险。 快速回答 # 最小化配置示例 - 仅用于测试或开发环境 export ES_JAVA_OPTS"-Xms512m -Xmx512m" ./bin/elasticsearch…

TI-92 Plus计算器:单位换算功能介绍

1 TI-92 Plus计算器&#xff1a;单位换算功能介绍 TI-92 Plus 内置了全面的单位换算功能&#xff0c;支持长度、质量、时间、温度、面积、体积、速度等数十种物理量的单位转换&#xff0c;操作直观&#xff0c;无需手动输入换算系数。以下是具体使用方法、示例及功能特点&#…

雪球科技Java开发工程师笔试题

单选 1.下列哪些语句关于内存回收的说明是正确的?( C ) A.内存回收程序允许程序员直接释放内存 B.程序员必须创建一个线程来释放内存 C.内存回收程序负责释放无用内存 D.内存回收程序可以在指定的时间释放内存对象 2.以下哪项不是Java基础类型(A) A.String B.int C.b…

NV3041A-01芯片屏幕

1. 核心概览这是一款集成了电源管理、显示内存&#xff08;RAM&#xff09;、时序控制等多种功能的单片显示驱动芯片&#xff08;通常称为Driver IC&#xff09;。它采用COG&#xff08;Chip-On-Glass&#xff09; 工艺&#xff0c;直接将芯片绑定在玻璃基板上&#xff0c;使得…

aiagent知识点

一、MCP (Model Context Protocol) 1. 核心概念是什么&#xff1a;MCP是一个开放协议&#xff0c;用于在应用&#xff08;如IDE、Agent&#xff09; 和工具/数据源&#xff08;如服务器、数据库&#xff09; 之间建立标准化的通信。目标&#xff1a;解决AI工具生态的碎片化问题…

第2节-过滤表中的行-WHERE

摘要&#xff1a;在本教程中&#xff0c;您将学习如何使用 PostgreSQL 的 WHERE 子句来筛选表中的行。 PostgreSQL WHERE 子句 SELECT FROM 语句从表中所有行的一个或多个列中查询数据。实际上&#xff0c;你经常需要选择满足某个条件的行。 要根据条件从表中筛选行&#xf…

IACheck赋能AI环评报告审核,推动环保设备制造行业发展

在“双碳目标”和绿色制造的背景下&#xff0c;环保设备制造行业正在迎来快速发展。然而&#xff0c;环评报告作为项目合规的“通行证”&#xff0c;却一直是企业最头疼的环节之一&#xff1a;编写复杂、审核周期长、错误率高。传统的审核模式不仅耗时耗力&#xff0c;还容易出…

常见的多态

一、核心概念多态&#xff08;Polymorphism&#xff09; 的字面意思是“多种形态”。在Java中&#xff0c;它指的是&#xff1a;同一个行为&#xff08;方法&#xff09;具有多个不同表现形式或形态的能力。更具体地说&#xff0c;它允许你&#xff1a;父类的引用指向子类的对象…

20250909_排查10.1.1.190档案库房综合管理系统20250908备份缺失问题+优化scp脚本(把失败原因记录进日志)并测试脚本执行情况

目录 一、现象(图中现象) 二、可能原因 1、本地源文件没生成(最可能原因) 2、清理逻辑误删 三、时间同步检查 1、运行命令查看当前时间源:w32tm /query /source 2、修改为内网 NTP 服务器 10.1.10.251: 四、脚本优化 1、scp.bat vs roboscp.bat 对比表 2、robo…

OpenHarmony之有源NFC-connected_nfc_tag模块详解

1. 模块概述 Connected NFC Tag模块是OpenHarmony NFC子系统的一部分,专门用于处理有源NFC标签的读写操作。与基础NFC模块不同,该模块专注于与已连接的有源NFC标签进行交互,提供更高层次的API供应用层使用。 设备必须具备有源NFC标签芯片,才能使用有源NFC标签的读和写服务…