Lambda 表达式

一、Lambda 是什么

一句话:

Lambda 表达式 = 轻量函数(匿名函数)

不需要声明名字、不需要单独写函数体,直接在代码里用。

二、C++ Lambda 基本格式

C++ 最完整语法:

capture\](parameter_list) mutable noexcept -\> return_type { body } 最常见精简格式: \[\&\](int x){ return x + 1; } ✳ **三、参数说明** | 部分 | 含义 | |--------------------|----------| | `[capture]` | 捕获外部变量 | | `(parameter_list)` | 参数列表 | | `mutable` | 允许修改捕获变量 | | `return_type` | 返回类型 | | `{ body }` | 实现代码 | ⚡ **四、捕获(capture)的写法重点** 捕获方式决定 Lambda 能否访问外部变量 例1:按值捕获 int a = 10; auto f = \[a\]() { return a + 1; }; 例2:按引用捕获 int a = 10; auto f = \[\&a\]() { a++; }; f(); 执行后 `a == 11` 例3:全部按值捕获 \[=\]() { ... } 例4:全部按引用捕获 \[\&\]() { ... } 例5:混合捕获 \[=,\&x\](){ ... } 🧰 **五、典型使用场景** **① 线程回调 / 异步执行** std::thread t(\[\]{ printf("worker\\n"); }); t.join(); **② STL 回调(最常用)** std::vector\ v{1,2,3,4}; std::for_each(v.begin(), v.end(), \[\](int x){ std::cout \<\< x \<\< " "; }); **③ 排序自定义** std::sort(v.begin(), v.end(), \[\](int a, int b){ return a \> b; }); 🔧 **六、底层实现** C++ Lambda 本质是: > 编译器生成一个匿名类(仿函数 functor) int a = 10; auto f = \[a\]() { return a+1; }; 等价于: struct _Lambda { int a; int operator()() const { return a+1; } }; 所以: * 捕获变量 → 编译器生成成员变量 * 调用 → 通过 `operator()` 执行 这一点和 `std::function` / function pointer 不一样。 ## 🚩 **七、常见坑** #### **❗ 1. 捕获值不会更新原变量** int a = 10; auto f = \[a\](){ return a++; }; f(); printf("%d\\n", a); // 输出 10(不会变) 需要引用: auto f = \[\&a\](){ a++; }; **❗ 2. 捕获 this** 类内使用很常见: auto f = \[this\]() { this-\>run(); }; 🚀 **八、和函数指针对比** | | 函数指针 | Lambda | |----------|-------|--------| | 是否捕获外部变量 | ❌ 不行 | ✔ 可以 | | 创建方式 | 需要函数名 | 无名即可 | | 内联优化 | 一般 | 强 | | 易用性 | 差 | 好 | 高级用法: 1️⃣ **泛型 Lambda (C++14+)** 允许参数类型自动推断: auto add = \[\](auto a, auto b){ return a + b; }; add(1, 2); // int add(1.5, 2.2); // double add("a"s, "b"s); // string 2️⃣ **可变参数 Lambda (C++20)** auto print = \[\](auto... args){ (std::cout \<\< ... \<\< args) \<\< "\\n"; }; print(1, "hello", 3.14); 3️⃣ **mutable 捕获值可修改** 默认按值捕获是 `const` 的: int x = 10; auto f = \[x\]() mutable { x++; return x; }; f(); // 11 4️⃣ **捕获 this 指针** 类内非常常见: auto f = \[this\] { doWork(); }; 如果你写: \[=

类内也隐式捕获 this

但 C++20 允许捕获 this 的副本(防悬垂):

auto f = [*this] { doWork(); };

等于复制整个对象避免悬空指针。


5️⃣ 初始化捕获(C++14+重要能力)

auto f = [val = std::move(bigObj)] {

use(val);

};

变量 val 只存在 Lambda 内

特别适合智能指针:

auto f = [p = std::make_shared<int>(5)] {

std::cout << *p;

};

甚至可以这样:

auto f = [i=0]() mutable {

return ++i;

};

f(); //1

f(); //2

这种行为 = 闭包(closure)状态保持

6️⃣ constexpr Lambda(C++17+)

constexpr auto sqr = [](int x) { return x*x; };

static_assert(sqr(5) == 25);

还能在编译期算 Fibonacci:

constexpr auto fib = [](int n){

if (n <= 1) return n;

return fib(n-1) + fib(n-2);

};

7️⃣ 返回类型显式指定

当需要强制返回类型:

auto f = [](int x) -> double {

if(x > 0) return x;

return 0.5;

};

8️⃣ Lambda + std::function

⚠ 注意性能区别:

复制代码
std::function<int(int)> f = [](int x){ return x + 1; };

会发生:

  • 类型擦除

  • 动态分配(可能)

  • 低效

推荐保留 auto

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

9️⃣ Lambda 做状态机(闭包)

比如计数器:

auto counter = [i = 0]() mutable {

return ++i;

};

counter(); //1

counter(); //2

counter(); //3

多线程共享状态:

auto sum = [total = std::atomic<int>(0)](int x) mutable {

total += x;

};

这就是函数式闭包的力量。

🔟 Lambda 捕获移动对象

最重要的例子:线程池任务提交

pool.push([task=std::move(task)]() mutable {

task();

});

高级技巧加一条:模板 Lambda(C++20)

auto add = []<typename T>(T a, T b){

return a + b;

};

底层实现补充

Lambda 本质上:

编译器生成 struct + operator()

带捕获:

复制代码
int x = 10;
auto f = [x]{ return x+1; };
等价于

struct _lambda {

int x;

int operator()() const { return x+1; }

};

🚩 性能注意点

写法 性能
auto lambda 🟢 最快
template lambda 🟢 最快
std::function 🔴 可能动态分配,慢
bind 🔴 更慢/不推荐

🧨 STL 中的高阶组合

std::sort(v.begin(), v.end(),

\](auto \&a, auto \&b){ return a.score \> b.score; } ); 过滤: auto it = std::remove_if(v.begin(), v.end(), \[\&\](auto \&n){ return n \< 0; });

相关推荐
2401_831824961 小时前
基于C++的区块链实现
开发语言·c++·算法
汉克老师2 小时前
GESP5级C++考试语法知识(六、链表(一)单链表)
c++·链表·单链表·快慢指针·进阶·gesp5级·gesp五级
m0_518019482 小时前
C++与机器学习框架
开发语言·c++·算法
qq_417695052 小时前
C++中的代理模式高级应用
开发语言·c++·算法
学嵌入式的小杨同学2 小时前
STM32 进阶封神之路(十九):ADC 深度解析 —— 从模拟信号到数字转换(底层原理 + 寄存器配置)
c++·stm32·单片机·嵌入式硬件·mcu·架构·硬件架构
xiaoye-duck2 小时前
《算法题讲解指南:动态规划算法--路径问题》--5.不同路径,6.不同路径II
c++·算法·动态规划
ambition202423 小时前
最大子数组和算法全解析:从暴力枚举到动态规划优化
数据结构·c++·算法
qq_461489333 小时前
C++与Qt图形开发
开发语言·c++·算法
小菜鸡桃蛋狗4 小时前
C++——类和对象(上)
开发语言·c++
2401_879503414 小时前
C++中的观察者模式变体
开发语言·c++·算法