当前位置: 首页 > news >正文

c++lambda表达式

前言:关于c++中lambda表达式很久之前就想写一个教程了


C++ Lambda 表达式教程

1. 什么是 Lambda 表达式?

Lambda 表达式是 C++11 引入的一种匿名函数对象,允许你在需要函数的地方直接定义内联函数,无需显式命名。它们常用于:

  • 作为算法(如 std::sortstd::for_each)的参数
  • 实现回调函数
  • 简化代码逻辑
2. 基本语法

Lambda 表达式的基本结构:

[capture list](parameter list) -> return type { function body }
  • 捕获列表 []:定义如何捕获外部变量(如 [x, &y]
  • 参数列表 ():类似普通函数的参数(可省略,如 []{};
  • 返回类型 -> type:可省略(编译器自动推导)
  • 函数体 {}:函数的具体实现

示例 1:最简单的 Lambda

[]() { std::cout << "Hello, Lambda!"; }();  // 直接调用
// 输出:Hello, Lambda!

示例 2:带参数和返回值

auto add = [](int a, int b) -> int { return a + b; };
std::cout << add(3, 4);  // 输出:7
3. 捕获列表详解

捕获列表决定了 lambda 如何访问外部变量:

捕获方式语法说明
无捕获[]不捕获任何外部变量,函数体内不能使用外部变量
值捕获[x, y]按值捕获变量 xy(复制一份到 lambda 内部)
引用捕获[&x, &y]按引用捕获变量 xy(直接访问外部变量)
混合捕获[x, &y]值捕获 x,引用捕获 y
隐式值捕获[=]按值捕获所有外部变量
隐式引用捕获[&]按引用捕获所有外部变量
混合隐式捕获[=, &x]按值捕获所有变量,但 x 按引用捕获

示例 3:值捕获与引用捕获

int x = 10;
auto value_capture = [x]() { return x + 1; };  // 值捕获
auto ref_capture = [&x]() { return x + 1; };   // 引用捕获x = 20;
std::cout << value_capture();  // 输出:11(捕获的是 x 的副本)
std::cout << ref_capture();    // 输出:21(捕获的是 x 的引用)
4. 递归 Lambda

若需要在 lambda 内部递归调用自身,需使用 std::function 显式声明类型:

示例 4:递归计算阶乘

#include <functional>std::function<int(int)> factorial = [&factorial](int n) {return (n <= 1) ? 1 : n * factorial(n - 1);
};std::cout << factorial(5);  // 输出:120
5. Lambda 在标准库中的应用

Lambda 常用于标准库算法中,替代传统的函数对象。

示例 5:使用 Lambda 排序

#include <algorithm>
#include <vector>std::vector<int> nums = {3, 1, 4, 1, 5};
std::sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; });  // 降序排序// 输出:5 4 3 1 1
for (int num : nums) std::cout << num << " ";

示例 6:使用 Lambda 过滤元素

#include <algorithm>
#include <vector>std::vector<int> nums = {1, 2, 3, 4, 5};
auto even_count = std::count_if(nums.begin(), nums.end(),[](int x) { return x % 2 == 0; });std::cout << "偶数数量:" << even_count;  // 输出:2
6. 可变 Lambda

默认情况下,值捕获的变量在 lambda 内部是只读的。若需要修改,需使用 mutable 关键字:

示例 7:可变 Lambda

int x = 10;
auto increment = [x]() mutable { x++; return x; };std::cout << increment();  // 输出:11
std::cout << x;            // 输出:10(外部 x 未被修改)
7. 泛型 Lambda(C++14+)

C++14 允许使用 auto 参数创建泛型 lambda:

示例 8:泛型 Lambda

auto add = [](auto a, auto b) { return a + b; };std::cout << add(3, 4);       // 输出:7(int + int)
std::cout << add(3.1, 4.2);   // 输出:7.3(double + double)
8. Lambda 与移动语义

C++14 允许使用初始化捕获(也称为广义捕获),支持移动语义:

示例 9:移动捕获

#include <memory>auto ptr = std::make_unique<int>(42);
auto lambda = [value = std::move(ptr)]() { return *value; };std::cout << lambda();  // 输出:42
9. 注意事项
  1. 生命周期问题:引用捕获时需确保引用的变量在 lambda 执行时仍然有效。
  2. 性能考虑:值捕获会复制变量,大型对象建议使用引用捕获。
  3. 可调用对象类型:普通 lambda 的类型是唯一的,不可直接比较;std::function 可存储任意可调用对象,但有额外开销。
10. 总结

Lambda 表达式使 C++ 代码更简洁、灵活,尤其在处理算法、回调等场景时优势明显。掌握 lambda 的关键在于理解捕获列表和参数传递方式,根据场景选择合适的捕获策略。

http://www.xdnf.cn/news/697717.html

相关文章:

  • Linux文件传输——curl命令详介
  • SAR ADC 比较器的offset 校正
  • 西门子SCL语言编写两台电机正反转控制程序,并涵盖从选型、安装到调试全过程的详细步骤指南(上)
  • vs中添加三方库的流程
  • 根据基因名称自动获取染色体上的位置
  • STM32 ADC工作原理与配置详解
  • 渐进够增强和优雅降级的区别
  • 8.5 Q1|中山大学CHARLS发文 | 甘油三酯葡萄糖-腰身高比指数与中国中老年人心血管疾病的关系
  • (8)python+ selenium自动化测试-获取当前页面的title
  • MCU与CPU时钟概念详解:从基础到面试高频问题
  • 第三届宁波技能大赛网络安全赛项样题
  • uniapp-商城-73-shop(6-商品列表,步进器添加数据到购物车,步进器数据同步(深度监听))
  • STM32定时器的死区时间(DTR)如何计算
  • Cancer Cell|从临床病例到AI空间组学 | 空间生物标志物如何精准预测HER2阳性乳腺癌ADC疗效?
  • 瑞数6代jsvmp简单分析(天津电子税x局)
  • B2146 Hermite 多项式
  • 15.为什么HashMap的容量是2的幂次方
  • 编译与链接,咕咕咕
  • 2.2 C++之循环结构
  • 弧度 = 弧长与半径的比值
  • Vitrual Studio调试windows应用程序如何打开控制台
  • 算法-背包问题
  • 火热邀测!DataWorks数据集成支持大模型AI处理
  • 让DeepSeek去除AI痕迹的指令
  • 数据库管理:探寻高效之路
  • webpack打包基本配置
  • 图像融合质量评价指标
  • cmake学习day01
  • [CARLA系列--03]如何打包生成CARLA 0.9.15的非编辑版(地图的加载与卸载)
  • NW845NW850美光闪存颗粒NW883NW889