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; });

相关推荐
端平入洛1 天前
delete又未完全delete
c++
端平入洛2 天前
auto有时不auto
c++
哇哈哈20213 天前
信号量和信号
linux·c++
多恩Stone3 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
蜡笔小马3 天前
21.Boost.Geometry disjoint、distance、envelope、equals、expand和for_each算法接口详解
c++·算法·boost
超级大福宝3 天前
N皇后问题:经典回溯算法的一些分析
数据结构·c++·算法·leetcode
weiabc3 天前
printf(“%lf“, ys) 和 cout << ys 输出的浮点数格式存在细微差异
数据结构·c++·算法
问好眼3 天前
《算法竞赛进阶指南》0x01 位运算-3.64位整数乘法
c++·算法·位运算·信息学奥赛
yyjtx3 天前
DHU上机打卡D31
开发语言·c++·算法
czxyvX3 天前
020-C++之unordered容器
数据结构·c++