## 2. Lambda 函数大全 ### 2.1 基础概念 * **定义**:一种匿名函数对象(closure object)。 * **语法结构**: ```cpp [捕获列表] (参数列表) -> 返回类型 { 函数体 } ``` * **返回类型可省略**:由 `return` 推导。 --- ### 2.2 捕获方式 假设外部有 `int a; int b;` | 捕获方式 | 含义 | | ----------- | ------------------- | | `[=]` | 按值捕获所有外部变量(只读) | | `[&]` | 按引用捕获所有外部变量 | | `[a]` | 按值捕获变量 `a` | | `[&a]` | 按引用捕获变量 `a` | | `[=, &b]` | 默认值捕获,单独指定引用捕获某些变量 | | `[&, a]` | 默认引用捕获,单独指定按值捕获某些变量 | | `[this]` | 捕获当前对象指针(隐式捕获成员变量) | | `[=, this]` | 按值捕获外部变量,同时捕获 this | --- ### 2.3 可变 Lambda (`mutable`) * 按值捕获默认是 **不可修改捕获变量副本** * 加 `mutable` 可以修改副本 ```cpp int x = 5; auto f = [=]() mutable { x += 1; }; // 修改的是副本 ``` --- ### 2.4 泛型 Lambda(C++14+) ```cpp auto add = [](auto a, auto b) { return a + b; }; ``` ```cpp C++20 auto add = [](const T& a, const T& b) { return a + b; }; ``` 相当于模板函数。 --- ### 2.5 返回类型 * **推导**(C++14+ 支持多返回类型推导一致性检查) * **显式声明**: ```cpp auto div = [](double a, double b) -> double { return a/b; }; ``` --- ### 2.6 存储与调用 * **立即调用**: ```cpp []{ std::cout << "Hi\n"; }(); ``` * **存储到变量**: ```cpp auto f = [](int x){ return x*x; }; std::cout << f(5); ``` --- ### 2.7 转换为函数指针 * 仅无捕获 Lambda 可转换: ```cpp void (*fp)(int) = [](int x){ std::cout << x; }; ``` --- ### 2.8 在 STL 中用作比较器 ```cpp auto cmp = [](int a, int b) { return a > b; }; std::priority_queue, decltype(cmp)> pq(cmp); ``` --- ## 3. `auto` + Lambda 联合技巧 1. **类型保存**(比较器、回调等): ```cpp auto cmp = [](int a, int b){ return a < b; }; std::set s(cmp); ``` 2. **推导返回类型**(泛型 + `auto`): ```cpp auto combine = [](auto a, auto b) { return a + b; }; ``` 3. **模板中传 Lambda**: ```cpp template void run(F f) { f(); } run([]{ std::cout << "run!\n"; }); ``` 4. **`decltype(auto)` 保持引用**: ```cpp auto getter = [](auto& c, size_t i) -> decltype(auto) { return c[i]; }; ``` --- 如果你愿意,我可以给你画一个 **`auto` 与 Lambda 的知识地图**,把所有用法和推导规则可视化,这样你看一次就能记住。这样对理解捕获机制和类型推导特别直观。 你要我画吗?这样你可以一眼就看全流程。