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<int> 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\(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\(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 小时前
独占指针的创建std::make_unique 本身自带堆出现
c++
kyle~1 小时前
ROS 2 与 Isaac Sim 联合仿真(一)体系架构、环境选型与基础通信闭环
c++·机器人·nvidia·仿真·ros2
努力努力再努力wz2 小时前
【内存管理与高并发内存池系列】从 mmap 到 malloc:文件映射、匿名映射与 glibc 内存分配机制详解
linux·c语言·数据结构·数据库·c++·qt·链表
八解毒剂2 小时前
数据结构-平衡二叉树——对二叉搜索树的优化
数据结构·c++·算法
起床困难户5752 小时前
条款20:协助完成返回值优化
c++
啦啦啦啦啦zzzz3 小时前
算法总结(二分查找、双指针)
c++·算法
不负岁月无痕4 小时前
C++ 模板核心内容与高频面试题汇总
java·开发语言·c++
无限进步_4 小时前
从零实现一个迷你Shell——深入理解Linux命令行解释器
linux·运维·服务器·开发语言·c++·chrome
fpcc5 小时前
工具使用——CMake中的函数和宏
c++·cmake
乐观勇敢坚强的老彭5 小时前
C++信息学奥赛lesson1
java·开发语言·c++