新闻详情

新闻详情

首页 / 资讯中心 / 详情

C++ Lambda 表达式详解:从基本语法到捕获列表

发布时间:2026/11/15 10:25:24来源:尧图网络
C++ Lambda 表达式详解:从基本语法到捕获列表
在学习 C 和 Qt 的过程中经常会看到这样的代码auto bitsum [](int x) - int { int res 0; while (x) { res x % 10; x / 10; } return res; };或者在 Qt 的connect()中看到connect(button, QPushButton::clicked, this, [sender]() { sender-sendData(); });刚开始看到[]、[sender]很容易疑惑。其实这两段代码使用的都是同一个 C 特性Lambda 表达式。本文从 Lambda 的基本语法开始重点介绍最容易混淆的捕获列表。一、什么是 Lambda 表达式Lambda 可以简单理解为在代码中直接定义一个匿名函数。例如普通函数int add(int a, int b) { return a b; }如果这个函数只使用一次其实没有必要专门给它起一个函数名。可以直接写成 Lambdaauto add [](int a, int b) - int { return a b; }; cout add(3, 5);输出8这里的add是一个变量它保存了这个 Lambda。因此可以通过add(3, 5);调用它。二、Lambda 的基本语法Lambda 的常见完整形式是[capture](parameters) - return_type { // 函数体 };例如auto add [](int a, int b) - int { return a b; };可以拆成[] (int a, int b) - int │ │ │ 捕获列表 参数列表 返回值类型最后{ return a b; }是 Lambda 的函数体。三、[]是什么Lambda 最前面的[]叫做捕获列表Capture List这是 Lambda 与普通函数一个非常重要的区别。捕获列表主要解决一个问题Lambda 如果需要使用外部作用域中的局部变量该怎么办例如void test() { int x 10; auto func []() { cout x; }; }这段代码会出错。因为x是test()中的局部变量而 Lambda 默认不能直接访问这个外部局部变量。可以通过捕获列表解决void test() { int x 10; auto func [x]() { cout x; }; }这里[x]表示把外面的x捕获到 Lambda 中。四、[x]按值捕获最基本的捕获方式是[x]表示按照值捕获x。例如int x 10; auto func [x]() { cout x; }; func();输出10可以把它简单理解成 Lambda 保存了一份x的副本。因此int x 10; auto func [x]() { cout x; }; x 20; func();输出仍然是10因为 Lambda 中保存的是捕获时的x副本。五、[x]按引用捕获如果写成[x]则表示按引用捕获x。例如int x 10; auto func [x]() { cout x; }; x 20; func();输出20因为 Lambda 访问的是外部原来的x。甚至可以直接修改它int x 10; auto func [x]() { x 100; }; func(); cout x;输出100所以可以简单记忆[x] → 按值捕获 [x] → 按引用捕获六、[]不捕获任何外部变量例如auto func []() { cout Hello; };这里[]表示不捕获任何外部局部变量。前面 LeetCode 中的数位和代码就是这种情况auto bitsum [](int x) - int { int res 0; while (x) { res x % 10; x / 10; } return res; };这里的x并不是外部变量。它来自(int x)也就是说x → Lambda 的参数而不是x → 外部变量所以根本不需要捕获。七、[]默认按值捕获如果外面有多个变量int a 10; int b 20; int c 30;可以写auto func []() { cout a endl; cout b endl; cout c endl; };[]表示Lambda 中使用到的外部局部变量默认按照值捕获。这样就不需要写[a, b, c]八、[]默认按引用捕获同理auto func []() { a; b; c; };表示Lambda 中使用到的外部局部变量默认按照引用捕获。因此[] → 默认按值捕获 [] → 默认按引用捕获这是非常常用的两种写法。九、捕获列表可以混合使用捕获列表并不只能全部按值或者全部按引用。例如int a 10; int b 20; auto func [a, b]() { cout a endl; b; };这里[a, b]表示a → 按值捕获 b → 按引用捕获也可以使用默认捕获方式再单独指定某个变量。例如[, b]表示默认按值捕获但是b按引用捕获。而[, a]表示默认按引用捕获但是a按值捕获。十、Lambda 中的“参数”和“捕获”不要混淆这是学习 Lambda 时非常容易混淆的地方。例如auto func [x](int y) - int { return x y; };这里有三个不同的部分[x] → 捕获列表 (int y) → 参数列表 - int → 返回值类型其中x是外部变量通过捕获列表进入 Lambda。而y是调用 Lambda 时传入的参数。例如int x 10; auto func [x](int y) - int { return x y; }; cout func(5);结果15所以捕获列表解决的是“Lambda 如何使用外部变量”参数列表解决的是“调用 Lambda 时如何传入参数”。十一、Lambda 在 Qtconnect()中的使用Lambda 在 Qt 中非常常见尤其是connect()。例如connect(button, QPushButton::clicked, this, []() { qDebug() 按钮被点击; });这里第四个参数就是一个 Lambda[]() { qDebug() 按钮被点击; }因为这个 Lambda 不需要使用外部局部变量所以捕获列表为空[]十二、Qt 中为什么会出现[sender]再看一个实际例子Sender *sender new Sender; connect(button, QPushButton::clicked, this, [sender]() { sender-sendData(); });这里Sender *sender new Sender;定义了一个局部变量sender而 Lambda 中需要使用这个变量sender-sendData();因此需要在捕获列表中写[sender]表示按值捕获外部的sender变量。这里尤其要注意Sender *sender中的sender是一个指针变量。所以[sender]捕获的是这个指针变量而不是Sender类型。可以简单理解为外部 sender ─────────→ Sender对象 │ │ 按值捕获 ↓ Lambda sender ─────────→ 同一个Sender对象指针本身复制了一份但是两个指针仍然指向同一个对象。十三、[sender]和[sender]的区别假设Sender *sender new Sender;那么[sender]表示按值捕获指针变量。而[sender]表示按引用捕获指针变量。也就是说两者的区别是[sender] ↓ 复制一份指针 [sender] ↓ 引用原来的指针变量在 Qt 的很多场景中如果只是需要 Lambda 使用这个指针常见写法就是[sender]十四、为什么 Lambda 在 Qt 中特别常见因为 Qt 的connect()可以直接接收 Lambda。例如connect(button, QPushButton::clicked, this, [this]() { ui-label-setText(Hello); });这里[this]也是一种捕获。它表示捕获当前对象的this指针。于是 Lambda 中可以使用ui-label等当前对象的成员。因此你在 Qt 项目中看到[this]()[sender]()[data]()本质上都是在使用 Lambda 的捕获列表。十五、Lambda 常见写法总结可以先记住下面这张表写法含义[]不捕获外部变量[x]按值捕获x[x]按引用捕获x[]外部变量默认按值捕获[]外部变量默认按引用捕获[a, b]a按值b按引用[, b]默认按值但b按引用[, a]默认按引用但a按值十六、回到最开始的 LeetCode 代码现在再看这段代码auto bitsum [](int x) - int { int res 0; while (x) { res x % 10; x / 10; } return res; };就很好理解了。auto bitsum ↓ 用一个变量保存 Lambda [] ↓ 不捕获外部变量 (int x) ↓ Lambda 的参数 - int ↓ 返回 int { ... } ↓ Lambda 函数体而 Qt 中[sender]() { sender-sendData(); }则是[sender] ↓ 按值捕获外部的 sender () ↓ 没有参数 { sender-sendData(); } ↓ 使用捕获进来的 sender因此理解 Lambda 最重要的就是先分清楚这三个部分[capture](parameters) - return_type其中捕获列表决定 Lambda 能不能使用外部变量以及如何捕获这些变量参数列表决定调用 Lambda 时接收什么参数返回值类型决定 Lambda 返回什么类型。掌握这几个基本概念后再看 C STL、Qtconnect()中的大量 Lambda 写法就不会再觉得[]、[this]、[sender]很神秘了。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/15 4:54:16

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/15 2:04:12

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/14 10:11:15

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/14 17:14:38

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/14 16:35:50

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/15 4:06:36

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉