【C++11】lambda表达式
前言:
随着 C++11 的发布,C++ 标准引入了许多新特性,使语言更加现代化,开发者编写的代码也变得更加简洁和易于维护。Lambda 表达式是其中一个重要的特性,它提供了一种方便的方式来定义匿名函数,这在函数式编程范式中非常常见。Lambda 表达式允许我们在函数内部定义小型的无名函数,减少了不必要的函数定义和代码冗余,是现代 C++ 开发的重要工具。
本文将详细介绍 C++11 中 Lambda 表达式的语法、使用场景、捕获机制以及高级应用,帮助读者充分理解并应用这个特性。
一、Lambda 表达式的基础
Lambda 表达式的基本语法如下:
[capture] (parameters) -> return_type { body }
capture(捕获列表):定义了哪些外部变量会被“捕获”并在lambda表达式内部使用。它可以按值或按引用捕获。parameters(参数列表):与普通函数的参数列表相似,定义了传递给lambda的参数。return_type(返回类型):指定返回类型,C++11 可以自动推导返回类型,因此该部分可以省略。body(函数体):lambda 实际执行的代码块。
一个简单的 Lambda 表达式示例:
auto add = [](int a, int b) -> int { return a + b; };
std::cout << add(5, 3) << std::endl; // 输出 8
这里我们定义了一个接受两个 int 参数并返回它们之和的匿名函数。lambda 通过 [] 定义了捕获列表,(int a, int b) 是参数列表,-> int 是返回类型,而函数体 { return a + b; } 执行了实际的操作。
二、捕获列表
捕获列表定义了 lambda 可以使用的外部变量。捕获方式分为两种:按值捕获和按引用捕获。通过不同的捕获方式,可以控制 lambda 对外部变量的访问和修改行为。
1. 不捕获任何变量
如果 lambda 不需要使用任何外部变量,可以使用空捕获列表:
auto sayHello = []() { std::cout << "Hello, World!" << std::endl; };
sayHello(); // 输出:Hello, World!
2. 按值捕获(=)
按值捕获意味着 lambda 内部得到的是捕获变量的副本,因此在 lambda 内对该变量的修改不会影响外部变量。
int x = 10;
auto captureByValue = [x]() { std::cout << x << std::endl; };
x = 20;
captureByValue(); // 输出 10
在上面的例子中,虽然我们在 lambda 定义之后修改了 x 的值,但 lambda 捕获的是 x 的副本,因此输出的仍然是 10。
3. 按引用捕获(&)
按引用捕获则允许 lambda 直接访问外部变量并修改它的值。
int x = 10;
auto captureByReference = [&x]() { x += 10; };
captureByReference();
std::cout << x << std::endl; // 输出 20
这里我们通过 &x 将 x 按引用捕获,因此在 lambda 中对 x 的修改会直接影响外部变量。
4. 捕获特定变量
可以只捕获特定的变量,而不是捕获所有外部变量。捕获方式可以是按值或按引用:
int a = 5, b = 10;
auto captureSpecific = [a, &b]() {std::cout << "a: " << a << std::endl;std::cout << "b: " << b << std::endl;b = 20;
};
captureSpecific();
std::cout << "b: " << b << std::endl; // 输出 20
在这个例子中,a 被按值捕获,b 被按引用捕获。lambda 内部修改了 b,而外部的 b 也受到了影响。
5. 捕获所有变量([=] 和 [&])
[=]:按值捕获所有外部变量。[&]:按引用捕获所有外部变量。
int x = 5, y = 10;
auto captureAllByValue = [=]() {std::cout << "x: " << x << ", y: " << y << std::endl;
};
captureAllByValue(); // 输出:x: 5, y: 10auto captureAllByReference = [&]() {x += 10;y += 10;
};
captureAllByReference();
std::cout << "x: " << x << ", y: " << y << std::endl; // 输出:x: 15, y: 20
通过 [=],lambda 按值捕获了 x 和 y,因此即使在外部修改了 x 和 y,lambda 内的 x 和 y 仍然保持不变。而通过 [&],lambda 可以直接修改外部的 x 和 y。
三、Lambda 表达式的返回类型
在 C++11 中,lambda 的返回类型可以自动推导,也可以显式指定。通常,如果 lambda 体中只有一个 return 语句,编译器会自动推导返回类型:
auto add = [](int a, int b) { return a + b; };
std::cout << add(3, 4) << std::endl; // 输出 7
如果 lambda 体中有复杂的逻辑或多个 return 语句,建议使用 -> 明确指定返回类型:
auto complexLambda = [](int a, int b) -> int {if (a > b) return a;else return b;
};
std::cout << complexLambda(3, 4) << std::endl; // 输出 4
自动推导有时会导致问题,特别是当 lambda 返回一个引用或指针时,明确返回类型显得尤为重要。
四、Lambda 的常见使用场景
1. 用于标准算法
C++ 标准库中提供了许多算法,如 std::sort、std::for_each 等,lambda 可以很方便地作为这些算法的回调函数使用。
std::vector<int> v = {1, 2, 3, 4, 5};
std::for_each(v.begin(), v.end(), [](int &n) { n *= 2; });
for (auto n : v) std::cout << n << " "; // 输出 2 4 6 8 10
在这个例子中,lambda 作为 std::for_each 的参数,将每个元素乘以 2。
2. 用于排序
使用 lambda 作为自定义排序条件,可以让排序更加灵活。
std::vector<int> v = {5, 2, 9, 1, 5, 6};
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
for (auto n : v) std::cout << n << " "; // 输出 9 6 5 5 2 1
这里,我们通过 lambda 定义了一个降序排序的条件。
3. 用于事件回调
在 GUI 或网络编程中,lambda 常用于定义事件的回调函数。例如,在按钮点击事件中:
button.onClick([]() {std::cout << "Button clicked!" << std::endl;
});
lambda 作为回调函数的使用使得代码更加简洁。
五、Lambda 表达式的高级用法
1. 捕获 this 指针
在类成员函数中,lambda 可以通过 [this] 捕获当前对象的 this 指针,这样就可以访问类的成员变量和成员函数。
class MyClass {
public:int value = 42;void printValue() {auto lambda = [this]() {std::cout << "Value: " << value << std::endl;};lambda();}
};int main() {MyClass obj;obj.printValue(); // 输出:Value: 42
}
通过捕获 this 指针,lambda 可以访问和修改对象的成员。
2. 可变的 Lambda 表达式
默认情况下,lambda 是不可修改其捕获的值的。如果需要修改捕获的值,可以在捕获列表后加上 mutable 关键字:
intx = 10;
auto mutableLambda = [x]() mutable {x += 10;std::cout << "Inside lambda: " << x << std::endl;
};
mutableLambda();
std::cout << "Outside lambda: " << x << std::endl; // 输出:Outside lambda: 10
mutable 使得 x 可以在 lambda 内部被修改,但不会影响外部的 x。
六、结语
C++11 的 Lambda 表达式为开发者提供了一种高效、简洁的方式来定义匿名函数,极大地增强了 C++ 的表达能力。理解并掌握 lambda 的使用方式,将有助于写出更现代、更易读的 C++ 代码 参考。
相关文章:
【C++11】lambda表达式
前言: 随着 C11 的发布,C 标准引入了许多新特性,使语言更加现代化,开发者编写的代码也变得更加简洁和易于维护。Lambda 表达式是其中一个重要的特性,它提供了一种方便的方式来定义匿名函数,这在函数式编程范…...
前端学习-css的背景(十六)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 背景颜色 语法格式 背景图片 语法格式 背景平铺 语法格式 背景图片位置 语法格式 参数代表的意思 参数是方位名词 参数是精确单位 参数是混合单位 背…...
使用Postman搞定各种接口token实战
现在许多项目都使用jwt来实现用户登录和数据权限,校验过用户的用户名和密码后,会向用户响应一段经过加密的token,在这段token中可能储存了数据权限等,在后期的访问中,需要携带这段token,后台解析这段token才…...
ssh连接慢的问题或远程连接服务超时
问题原因: 在SSH登录过程中,服务器会通过反向DNS查找客户端的主机名,然后与登录的IP地址进行匹配,以验证登录的合法性。如果客户端的IP没有域名或DNS服务器响应缓慢,这可能导致SSH登录过慢。为了解决这个问题…...
基于卷积神经网络的蔬菜识别系统,resnet50,mobilenet模型【pytorch框架+python源码】
更多目标检测和图像分类识别项目可看我主页其他文章 功能演示: 基于卷积神经网络的蔬菜识别系统,resnet50,mobilenet【pytorch框架,python,tkinter】_哔哩哔哩_bilibili (一)简介 基于卷积神…...
数据结构与算法:栈与队列的高级应用
目录 3.1 栈的高级用法 3.2 队列的深度应用 3.3 栈与队列的综合应用 总结 数据结构与算法:栈与队列的高级应用 栈和队列是两种重要的线性数据结构,它们在计算机科学和工程的许多领域都有广泛的应用。从函数调用到表达式求值,再到任务调度…...
macos php开发环境之macport安装的php扩展安装,php常用扩展安装,port中可用的所有php扩展列表
macos中,我们使用了port 安装了php后,默认只带有php基本的核心扩展的, 如果需要使用其他的扩展,如 redis, https, xdebug等扩展就需要我们手动来安装对应的扩展。 macos php开发环境 macport安装的php的方法见macos 中…...
使用Pytorch+Numpy+Matplotlib实现手写字体分类和图像显示
文章目录 1.引用2.内置图片数据集加载3.处理为batch类型4.设置运行设备5.查看数据6.绘图查看数据图片(1)不显示图片标签(2)打印图片标签(3)图片显示标签 7.定义卷积函数8.卷积实例化、损失函数、优化器9.训练和测试损失、正确率(1)训练(2)测试(3)循环(4)损失和正确率曲线(5)输出…...
kimi帮我解决ubuntu下软链接文件夹权限不够的问题
我的操作如下 ubuntuubuntu-QiTianM420-N000:~$ ln -s /media/ubuntu/4701aea3-f883-40a9-b12f-61e832117414 code ubuntuubuntu-QiTianM420-N000:~$ ls -l 总用量 636 drwxrwxr-x 2 ubuntu ubuntu 4096 5月 7 17:16 bin drwxrwxrwx 2 ubuntu ubuntu 4096 5月 8 13…...
如何去除背景音乐保留人声?保留人声,消除杂音
在日常生活和工作中,我们经常遇到需要处理音频的情况,尤其是当我们想要去除背景音乐,仅保留人声时。这种需求在处理电影片段、制作音乐MV、或者提取演讲内容等场景中尤为常见。本文将为您详细介绍如何去除背景音乐并保留人声,帮助…...
2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数
2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数 2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数 文章目录 2.4.ReactOS系统提升IRQL级别KfRaiseIrql 函数KfRaiseIrql 函数 KfRaiseIrql 函数 /*********************************************************************** NAME …...
【新书】使用 OpenAI API 构建 AI 应用:利用 ChatGPT等构建 10 个 AI 项目(第二版),404页pdf
通过构建 ChatGPT 克隆、代码错误修复器、测验生成器、翻译应用、自动回复邮件生成器、PowerPoint 生成器等项目,提升您的应用开发技能。 关键特性 通过掌握 ChatGPT 概念(包括微调和集成),转变为 AI 开发专家 通过涵盖广泛 AI …...
修改PostgreSQL表中的字段排列顺序
二、通过修改系统表(pg_attribute)达到字段重新排序的目的有关系统表的概述及用途可以查看官网:http://www.pgsqldb.org/pgsqldoc-cvs/catalogs.html 表名字表用途pg_class表,索引,序列,视图(”关系”)pg_…...
canvas实现手写功能
1.从接口获取手写内容,处理成由单个字组成的数组(包括符号) 2.合成所有图的时候,会闪现outputCanvas合成的图,注意隐藏 3.可以进行多个手写内容切换 4.基于uniapp的 <template><view class"content&quo…...
Python知识点:基于Python技术,如何使用TensorFlow进行目标检测
开篇,先说一个好消息,截止到2025年1月1日前,翻到文末找到我,赠送定制版的开题报告和任务书,先到先得!过期不候! 使用TensorFlow进行目标检测的完整指南 目标检测是计算机视觉领域中的一项重要任…...
初始爬虫13(js逆向)
为了解决网页端的动态加载,加密设置等,所以需要js逆向操作。 JavaScript逆向可以分为三大部分:寻找入口,调试分析和模拟执行。 1.chrome在爬虫中的作用 1.1preserve log的使用 默认情况下,页面发生跳转之后…...
前端发送了请求头的参数,经debug发现后端请求对象请求头中没有该参数
debug测试,发现前端发来请求头中确实没有找到添加的请求头参数,但是 Network 中却显示请求头中有该参数信息。 原因是RequestHeaders中设置的请求参数含有下划线,NGINX将静默地丢弃带有下划线的HTTP标头,这样做是为了防止在将头映…...
雷池社区版如何使用静态资源的方式建立站点
介绍: SafeLine,中文名 “雷池”,是一款简单好用, 效果突出的 Web 应用防火墙(WAF),可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、X…...
车载电源OBC+DC/DC
文章目录 1. 车载DC/DC应用场景2. PFC2.1 简介2.2 专业名词2.3 常见拓扑结构2.3.1 传统桥式PFC2.3.2 普通无桥型PFC2.3.3 双Boost无桥PFC2.3.4 图腾柱PFC2.3.5 参考资料 2.4 功率因数2.4.1 简介2.4.2 计算 3. DC/DC3.1 Boost升压电路3.1.1 简介3.1.2 电路框图3.1.3 工作原理3.1…...
【朝花夕拾】免费个人网页搭建:免费托管、CDN加速、个人域名、现代化网页模板一网打尽
现代化网页设计的免费宝藏:GitHub PagesCodePenCloudflareUS.KG 前言 在当今数字化时代,个人和企业越来越重视在线形象的建立。GitHub Pages 提供了一个免费且便捷的平台,允许用户托管静态网站。然而,GitHub Pages 默认的域名可…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
