news 2026/4/17 17:08:15

C/C++知识积累-Lambda表达式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C/C++知识积累-Lambda表达式

目录

定义

语法结构

常见捕获列表

常见使用场景

Lambda的本质

Lambda的发展和问题


定义

C++中的Lambda表达式是C++11引入的新特性,允许在代码中定义匿名函数。简单而言,他就是一个匿名函数对象,通常用于简单、不需要复用、或者需要访问当前上下文变量的场景。

语法结构

Lambda表达式完整语法如下:

[捕获列表](参数类型) mutable 异常属性 -> 返回类型 {函数体}
  1. [捕获列表],这时Lambda核心。它定义了Lambda表达式函数体内部可以访问外部作用域中哪些变量,以及如何访问。
  2. (参数类型),相当于正常函数的参数列表。
  3. mutable可选。默认情况下,通过“值捕获”进来的变量都是只读的(const)。加上mutable后,才可以修改他们。但注意这里修改的是Lambda内部的拷贝值,外部值并不会实际修改。可以理解为正常情况下形参加了const修饰,加入mutable形参没有const修饰,但仍是形参。
  4. 异常属性绝大多数指的是noexcept,这个之前聊过就是向编译器和程序员承诺,这个函数不会抛出异常,常用于性能优化时添加。(编译器优化,生成更精简的指令;移动语义,实现“移动数据”而不是“拷贝数据”)。
  5. -> 返回类型。这相当于显示告知编译器该函数的返回类型,但一般可省略,因为编译器会根据返回的值自动推导出返回类型和auto类似。常用于编译器推导不出、强制类型转换和返回引用时(Lambda默认返回的是“值”(拷贝))。

大部分情况下,都会是[捕获列表] (mutable根据需要)(参数类型){函数体}的形式,异常属性和-> 返回类型都是省略不写的。

常见捕获列表

写法含义
[]不捕获任何外部变量。
[=]值捕获所有外部变量(Lambda 内持有的是副本,只读)。
[&]引用捕获所有外部变量(Lambda 内操作的是本体,可读写)。
[x]值捕获变量x,不捕获其他。
[&x]引用捕获变量x,不捕获其他。
[=, &y]默认值捕获所有,但变量y引用捕获
[&, x]默认引用捕获所有,但变量x值捕获
[this]捕获当前类的this指针(让 Lambda 能访问类的成员变量/函数)。

常见使用场景

1.场景一:配合STL一起使用。

#include<vector> #include <iostream> int main() { std::vector<int> v = {4, 3, 2, 1, 5}; std::sort(v.begin(), v.end()); //默认情况下是从小到大排序 for (int i : v) { std::cout << i << " "; } std::cout << std::endl; //使用Lambda表达式进行自定义排序 std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; // 从大到小排序 }); for (int i : v) { std::cout << i << " "; } std::cout << std::endl; return 0; }

2.场景二:捕获外部变量同时不想传一堆参数时。

#include<vector> #include <iostream> int main() { std::vector<int> v = {4, 3, 2, 1, 5}; std::sort(v.begin(), v.end()); int value = 2; //通过Lambda找出第一个大于2的元素 auto it = std::find_if(v.begin(), v.end(), [value](int x) { return x > value; }); if (it != v.end()) { std::cout << "First number > " << value << " is " << *it << std::endl; } return 0; }

3.场景三:mutable关键字的使用。

#include <iostream> int main() { int x = 5; // 按值捕获 x。如果没有 mutable, x++ 会报错 auto f = [x]() mutable { x++; std::cout << "x Value: " << x << std::endl; }; f(); f(); std::cout << "Outside: " << x << std::endl; // 输出 Outside: 5 (外部变量未变) return 0; }

Lambda的本质

在C++编译器眼中,Lambda表达式本质是一个匿名的“仿函数”对象。

例如当写下以下代码时,

int a = 10; auto f = [a](int x) { return a + x; };

编译器会自动生成匿名类,类似于:

class __AnonymousLambda { private: int m_a; // 对应捕获列表 [a] public: __AnonymousLambda(int a) : m_a(a) {} // 构造函数 // 对应函数体,参数列表 int operator()(int x) const { return m_a + x; } };

这就是为什么Lambda可以拥有状态,也可以当作参数传递。

Lambda的发展和问题

C++14增强了Lambda表达式,允许在参数列表中使用auto,使得lambda更加灵活,类似于模版函数,如下所示:

auto add = [](auto x, auto y) { return x + y; } std::cout << add(1, 2) << std::endl; // int相加,输出 3 std::cout << add(1.5, 2.5) << std::endl; // double相加,输出 4.0 std::cout << add(std::string("Hi "), "C++"); // string相加

同时,在使用Lambda时,要注意可能出现的问题,Lambda的生命周期。

当使用了引用捕获,而Lambda的生命周期长于被捕获变量的生命周期(比如在一个函数中返回了一个 Lambda,该 Lambda 引用了函数内的局部变量),这会导致悬垂引用,进而引发程序崩溃。

错误实例如下:

std::function<void()> getPrinter() { int value = 42; // 错误!引用捕获了局部变量 value // 当 getPrinter 返回时,value 被销毁,Lambda 内部持有了无效引用 return [&]() { std::cout << value << std::endl; }; }

这种情况下,将引用捕获[&]改成值捕获[=]或者[value]即可。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/17 12:28:56

FilamentPHP 3.3.15版本发布:表单构建革命与性能飞跃

FilamentPHP 3.3.15版本发布&#xff1a;表单构建革命与性能飞跃 【免费下载链接】filament filament&#xff1a;这是一个基于Laravel框架的模块化CMS系统&#xff0c;适合搭建企业级网站和应用程序。特点包括模块化设计、易于扩展、支持多语言等。 项目地址: https://gitco…

作者头像 李华
网站建设 2026/4/16 20:09:47

JavaScript如何实现大文件上传的断点续传与秒传?

大文件传输解决方案设计与实施建议 需求分析与现状评估 作为上海IT行业软件公司项目负责人&#xff0c;针对贵司提出的大文件传输功能需求&#xff0c;我进行了全面分析&#xff1a; 核心需求&#xff1a; 单文件100G传输能力文件夹层级结构保持高可靠性断点续传(支持浏览器刷…

作者头像 李华
网站建设 2026/4/17 8:56:31

智能飞船生成新纪元:AI助你轻松打造3D宇宙舰队

智能飞船生成新纪元&#xff1a;AI助你轻松打造3D宇宙舰队 【免费下载链接】SpaceshipGenerator A Blender script to procedurally generate 3D spaceships 项目地址: https://gitcode.com/gh_mirrors/sp/SpaceshipGenerator 还在为复杂的3D建模软件望而却步&#xff1…

作者头像 李华
网站建设 2026/4/17 8:52:47

10个BlenderMCP像素化技巧:让你的3D模型瞬间变身复古游戏资产

还在为3D模型转像素艺术而头疼吗&#xff1f;&#x1f914; 别担心&#xff0c;今天我要分享的BlenderMCP像素化转换技巧&#xff0c;能让你的创作效率翻倍&#xff01;无论你是游戏开发者、像素艺术爱好者&#xff0c;还是想要尝试新风格的3D设计师&#xff0c;这些方法都能帮…

作者头像 李华
网站建设 2026/4/17 8:16:51

24、RAC集群性能监控全解析

RAC集群性能监控全解析 在现代复杂的应用架构系统中,性能瓶颈可能出现在应用层、数据库层或操作系统层等各个地方。因此,对RAC(Real Application Clusters)集群进行全面的性能监控至关重要。我们可以从Oracle和Linux两个层面来进行监控。 1. Oracle性能监控 1.1 Enterpr…

作者头像 李华