【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 默认的域名可…...
MATLAB 数值计算辅助:分析 Stable Yogi 生成图像的色彩与纹理特征
MATLAB 数值计算辅助:分析 Stable Yogi 生成图像的色彩与纹理特征 1. 引言 最近在尝试用 Stable Yogi 生成一些皮革纹理的设计图,效果确实挺惊艳的。但生成得多了,就遇到一个新问题:我手头攒了几百张图,风格各异&…...
ESP32开发实战:5分钟搞定MicroPython调用C库驱动LED(附完整代码)
ESP32混合编程实战:用MicroPython调用C库实现高性能LED控制 在物联网设备开发中,ESP32凭借其出色的性价比和丰富的功能接口成为硬件开发者的首选。而MicroPython作为嵌入式领域的Python实现,以其简洁的语法和快速的开发周期赢得了大量开发者的…...
从Siwave导入模型到Q3D仿真,如何避免‘幽灵’solder导致的网络报错?
从Siwave到Q3D的模型迁移:彻底解决"幽灵焊料"引发的网络冲突 当你在Ansys电子设计自动化工具链中切换工作环境时,是否遇到过这样的困扰:从Siwave精心准备的模型导入Q3D后,突然冒出各种莫名其妙的网络重叠报错ÿ…...
The Leather Archive应用案例:从赛博都市到极简主义的皮衣穿搭
The Leather Archive应用案例:从赛博都市到极简主义的皮衣穿搭 1. 项目概述 「The Leather Archive」是一个基于AI技术的高端皮衣穿搭生成系统,它巧妙融合了Anything V5基础模型与Stable Yogi皮衣系列LoRA的专业能力。与传统AI工具不同,该项…...
Leptin30;YQQVLTSLPSQNVLQIANDLENLRDLLHLL (mouse)
一、基本信息名称: Leptin30(小鼠源瘦素功能片段肽)单字母序列: YQQVLTSLPSQNVLQIANDLENLRDLLHLL三字母序列: Tyr-Gln-Gln-Val-Leu-Thr-Ser-Leu-Pro-Ser-Gln-Asn-Val-Leu-Gln-Ile-Ala-Asn-Asp-Leu-Glu-Asn-Leu-Arg-Asp…...
5个高效实用的英雄联盟工具集使用指南
5个高效实用的英雄联盟工具集使用指南 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit是一款基于LCU API开发的开源…...
手指划过屏幕放大模型界面,环氧树脂层和纤维基体在激光路径下呈现出清晰的物理场分布。突然发现这个双层材料烧蚀模型跑得格外顺畅——看来前几天通宵调参没白费
comsol激光清洗、烧蚀双层材料 表面一层50μm厚度的环氧树脂(可更换成其他材料),基体材料为纤维材料。 添加功率为13W的激光进行清洗或烧蚀 模型非常成功、角度选择很奈斯在COMSOL里建模时有个小细节特别关键:把环氧树脂层的厚度参数设为全局变量。别小看…...
霜儿-汉服-造相Z-Turbo实战体验:输入一句话,秒获专属汉服少女AI写真
霜儿-汉服-造相Z-Turbo实战体验:输入一句话,秒获专属汉服少女AI写真 1. 惊艳效果展示:从文字到古风美图的魔法 想象一下,你只需要输入"霜儿,古风汉服少女,月白霜花刺绣汉服,江南庭院&quo…...
面向对象编程入门(下篇):继承、封装与多态
在上篇中,我们学会了如何定义类和创建对象,将现实世界的事物用代码表示。今天,我们将深入面向对象编程的三大核心特性:继承、封装和多态。这些特性将让你的代码更加灵活、可扩展和易维护。一、继承:代码复用的“家族传…...
影墨·今颜小红书模型与Claude Code的协同编程应用设想
影墨今颜小红书模型与Claude Code的协同编程应用设想 最近在琢磨一个挺有意思的组合:让擅长生成代码的Claude Code和专门为小红书内容优化的影墨今颜模型一起干活。听起来有点跨界,但仔细想想,这俩搭档起来,说不定能解决不少实际…...
