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

C++ labmbd表达式

文章目录

      • C++ Lambda 表达式详解
      • 1. Lambda 表达式的组成部分:
      • 2. Lambda 语法示例
        • (1) 最简单的 Lambda
        • (2) 带参数的 Lambda
        • (3) 指定返回类型的 Lambda
      • 3. 捕获外部变量
        • (1) 值捕获(复制)
        • (2) 引用捕获
        • (3) 捕获所有变量
      • 4. Lambda 在 STL 中的应用
      • 5. Lambda 作为 `std::function`
      • 6. 可变 (`mutable`) Lambda
      • 7. Lambda 递归
      • 总结


C++ Lambda 表达式详解

Lambda 表达式(也称为匿名函数)是一种简洁的方式来定义即用即弃的函数对象,特别适用于回调、并行算法和函数式编程风格。Lambda 表达式的基本语法如下:

[capture](parameters) -> return_type { function_body }

1. Lambda 表达式的组成部分:

组件作用
[capture]捕获外部作用域变量
(parameters)形参列表(可省略)
-> return_type返回值类型(可省略,编译器可推导)
{ function_body }函数体

2. Lambda 语法示例

(1) 最简单的 Lambda
#include <iostream>

int main() {
    auto lambda = [] { std::cout << "Hello, Lambda!" << std::endl; };
    lambda(); // 调用 lambda
    return 0;
}

说明

  • [] 表示没有捕获外部变量。
  • 没有参数和返回值,直接执行 {} 内部的代码。

(2) 带参数的 Lambda
#include <iostream>

int main() {
    auto add = [](int a, int b) { return a + b; };
    std::cout << add(3, 5) << std::endl; // 输出 8
    return 0;
}

说明

  • [](int a, int b) { return a + b; } 是一个接收两个 int 参数并返回它们和的 Lambda 表达式。
  • auto add 变量接收 Lambda,可像普通函数一样调用。

(3) 指定返回类型的 Lambda
#include <iostream>

int main() {
    auto divide = [](int a, int b) -> double { return (double)a / b; };
    std::cout << divide(5, 2) << std::endl; // 输出 2.5
    return 0;
}

说明

  • -> double 明确指定了返回类型,否则 a / b 可能会被推导为 int

3. 捕获外部变量

Lambda 可以访问其作用域内的变量,但必须通过捕获列表 [] 指定是否捕获它们。

(1) 值捕获(复制)
#include <iostream>

int main() {
    int x = 10;
    auto lambda = [x]() { std::cout << x << std::endl; };
    x = 20; // lambda 捕获的是 10,不受影响
    lambda(); // 输出 10
    return 0;
}

说明

  • [x] 捕获 x 的值,lambda 内部访问的是捕获时的值,不受 x 变化影响。

(2) 引用捕获
#include <iostream>

int main() {
    int x = 10;
    auto lambda = [&x]() { std::cout << x << std::endl; };
    x = 20; // lambda 捕获的是引用,会受影响
    lambda(); // 输出 20
    return 0;
}

说明

  • [&x] 捕获 x 的引用,因此 x 的修改会影响 Lambda 内部的 x

(3) 捕获所有变量
#include <iostream>

int main() {
    int a = 5, b = 10;
    
    auto value_capture = [=]() { std::cout << a << " " << b << std::endl; };
    auto ref_capture = [&]() { std::cout << a << " " << b << std::endl; };

    a = 20; b = 30;

    value_capture(); // 仍然输出 5 10(值捕获不会变)
    ref_capture();   // 输出 20 30(引用捕获受外部变量影响)

    return 0;
}

说明

  • [=]:值捕获所有变量(a, b 被拷贝)。
  • [&]:引用捕获所有变量(a, b 直接访问原始变量)。

4. Lambda 在 STL 中的应用

Lambda 在 std::sort 等标准库函数中很常见:

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> nums = {4, 2, 7, 1, 9};
    
    std::sort(nums.begin(), nums.end(), [](int a, int b) { return a < b; });

    for (int num : nums) {
        std::cout << num << " "; // 输出 1 2 4 7 9
    }

    return 0;
}

说明

  • std::sort 需要一个比较函数,Lambda 可直接提供简洁的方式。

5. Lambda 作为 std::function

Lambda 还能存储到 std::function 变量中,方便传递:

#include <iostream>
#include <functional>

int main() {
    std::function<int(int, int)> multiply = [](int a, int b) { return a * b; };
    
    std::cout << multiply(3, 4) << std::endl; // 输出 12

    return 0;
}

6. 可变 (mutable) Lambda

默认情况下,值捕获的 Lambda 内部不能修改捕获的变量:

#include <iostream>

int main() {
    int x = 10;
    auto lambda = [x]() mutable { x = 20; std::cout << x << std::endl; };
    
    lambda(); // 输出 20
    std::cout << x << std::endl; // 仍然是 10(外部 x 没变)

    return 0;
}

说明

  • mutable 允许修改值捕获的 x,但该修改不会影响原始 x

7. Lambda 递归

Lambda 默认不能递归调用自己,但可以用 std::function 解决:

#include <iostream>
#include <functional>

int main() {
    std::function<int(int)> factorial = [&](int n) {
        return (n <= 1) ? 1 : n * factorial(n - 1);
    };

    std::cout << factorial(5) << std::endl; // 输出 120
    return 0;
}

说明

  • std::function<int(int)> 用于存储 Lambda,使其能递归调用自身。

总结

语法说明
[] {}无参数、无返回值的 Lambda
[](int x) { return x * 2; }带参数和返回值的 Lambda
[x] {}值捕获变量 x
[&x] {}引用捕获变量 x
[=] {}值捕获所有变量
[&] {}引用捕获所有变量
mutable允许修改值捕获的变量
std::function存储 Lambda 并支持递归

Lambda 表达式是 C++ 现代编程的重要特性,广泛用于 STL、并行计算和回调函数中。


http://www.kler.cn/a/536437.html

相关文章:

  • 从 .NET Framework 升级到 .NET 8 后 SignalR 问题处理与解决方案
  • 【GitHub】相关工具下载及使用
  • 深度学习:解码智能的“数字炼金术”
  • k8s网络插件及基础命令
  • Vue el-input密码输入框 按住显示密码,松开显示*;阻止浏览器密码回填,自写密码输入框;校验输入非汉字内容;文本框聚焦到内容末尾;
  • 深入浅出 NRM:加速你的 npm 包管理之旅
  • 在 Flownex 中创建自定义工作液
  • 寻找2020
  • 【算法】动态规划专题⑥ —— 完全背包问题 python
  • Maven 依赖管理全面解析
  • 【有啥问啥】什么是CTC(Connectionist Temporal Classification)算法
  • leetcode_双指针 541. 反转字符串 II
  • KAFKA-UI升级教程,因旧版本不支持(KAFKA-3.8.0 开启SASL认证)
  • Python基于Django的课堂投票系统的设计与实现【附源码】
  • Linux系统用户分类、UID与GID的区别、用户管理的基础命令
  • 【AIGC魔童】DeepSeek v3提示词Prompt书写技巧
  • 深度学习|表示学习|训练优化方法|Nesterov动量一定比基础的Momentum更好吗?|22
  • 基于LMStudio本地部署DeepSeek R1
  • elasticsearch安装插件analysis-ik分词器(深度研究docker内elasticsearch安装插件的位置)
  • Deepseek-v3 / Dify api接入飞书机器人go程序
  • 你是否想过,让AI像人类一样协作竞争?——展望智能体协作新范式
  • 数据结构-基础
  • 华为昇腾报:aclrtMemMallocPolicy:ACL_MEM_MALLOC_HUGE_FIRST
  • 三极管的截止、放大、饱和区
  • python2048游戏
  • 分形的魅力:数学与艺术的完美结合