C++匿名函数

C++ 中的匿名函数(Lambda 表达式)是 C++11 引入的一项重要特性,它允许你在需要的地方定义一个临时的、无名的函数对象,使代码更加简洁和灵活。

1. 基本语法

Lambda 表达式的基本结构:

cpp 复制代码
[capture list](parameter list) -> return type { function body }
  • [capture list]:捕获外部变量,指定如何将外部作用域的变量传递给 lambda。
  • (parameter list):参数列表,与普通函数的参数类似(可省略,但若省略括号必须为空)。
  • -> return type:返回类型(可省略,编译器会自动推导)。
  • { function body }:函数体,包含具体的实现逻辑。

示例

cpp 复制代码
auto add = [](int a, int b) -> int { return a + b; };
int result = add(3, 4);  // 结果为 7

2. 捕获列表(Capture List)

捕获列表用于访问外部作用域中的变量,有以下几种方式:

值捕获(By Value)
  • 使用 [var] 捕获变量的副本。
  • Lambda 创建时拷贝变量,后续修改不影响 lambda 内部的值。
cpp 复制代码
int x = 10;
auto lambda = [x]() { return x * 2; };  // 捕获 x 的值
x = 20;
std::cout << lambda();  // 输出 20(捕获的是 x 的副本)
引用捕获(By Reference)
  • 使用 [&var] 捕获变量的引用。
  • Lambda 内部使用的是变量的引用,外部修改会影响 lambda 内部。
cpp 复制代码
int x = 10;
auto lambda = [&x]() { return x * 2; };  // 捕获 x 的引用
x = 20;
std::cout << lambda();  // 输出 40(引用 x 的当前值)
隐式捕获
  • 使用 [=] 捕获所有外部变量的值(值捕获)。
  • 使用 [&] 捕获所有外部变量的引用(引用捕获)。
cpp 复制代码
int a = 5, b = 10;
auto lambda = [=]() { return a + b; };  // 值捕获 a 和 b
auto lambda2 = [&]() { a++; return a + b; };  // 引用捕获 a 和 b
混合捕获
  • 同时使用值捕获和引用捕获,例如 [=, &a](默认值捕获,a 引用捕获)。
cpp 复制代码
int a = 5, b = 10;
auto lambda = [=, &a]() { a++; return a + b; };  // a 引用捕获,b 值捕获

3. 参数列表

Lambda 的参数列表与普通函数类似,但不支持默认参数。

cpp 复制代码
auto greet = [](const std::string& name) {
    std::cout << "Hello, " << name << "!" << std::endl;
};
greet("Alice");  // 输出 "Hello, Alice!"

4. 返回类型

返回类型可省略,编译器会自动推导。若需要显式指定,使用 -> type

cpp 复制代码
auto sum = [](int a, int b) -> int { return a + b; };  // 显式指定返回类型
auto square = [](double x) { return x * x; };  // 自动推导返回类型

5. 可变 Lambda(Mutable Lambda)

默认情况下,值捕获的变量在 lambda 内部是只读的。使用 mutable 关键字可修改值捕获的变量。

cpp 复制代码
int x = 10;
auto lambda = [x]() mutable {
    x++;  // 允许修改值捕获的 x
    return x;
};
std::cout << lambda();  // 输出 11(但外部 x 仍为 10)

6. 泛型 Lambda(C++14+)

使用 auto 作为参数类型,使 lambda 成为泛型函数。

cpp 复制代码
auto print = [](const auto& value) {
    std::cout << value << std::endl;
};
print(42);      // 输出整数
print("test");  // 输出字符串

7. 捕获 this 指针

在类成员函数中,可捕获 this 指针以访问类的成员变量和方法。

cpp 复制代码
class MyClass {
public:
    int value = 10;
    void func() {
        auto lambda = [this]() { return value * 2; };
        std::cout << lambda();  // 输出 20
    }
};

8. 捕获初始化(C++14+)

允许在捕获列表中初始化新变量,可移动构造对象或重命名捕获的变量。

cpp 复制代码
int x = 10;
auto lambda = [y = x + 5]() { return y; };  // 初始化 y 为 15
std::cout << lambda();  // 输出 15

// 移动捕获(适用于不可复制的对象,如 std::unique_ptr)
auto ptr = std::make_unique<int>(42);
auto lambda2 = [ptr = std::move(ptr)]() { return *ptr; };

9. Lambda 的类型和存储

  • Lambda 表达式的类型是一个唯一的、未命名的闭包类型(Closure Type)。
  • 可使用 autostd::function 存储 lambda。
cpp 复制代码
// 使用 auto(推荐,效率更高)
auto add = [](int a, int b) { return a + b; };

// 使用 std::function(需包含 <functional>)
std::function<int(int, int)> multiply = [](int a, int b) { return a * b; };

10. Lambda 在 STL 中的应用

Lambda 常用于简化 STL 算法的使用。

cpp 复制代码
#include <algorithm>
#include <vector>

std::vector<int> nums = {1, 2, 3, 4, 5};

// 使用 lambda 作为谓词
auto sum = std::accumulate(nums.begin(), nums.end(), 0, 
                          [](int acc, int x) { return acc + x; });

// 排序
std::sort(nums.begin(), nums.end(), 
         [](int a, int b) { return a > b; });  // 降序排序

// 查找第一个大于 3 的元素
auto it = std::find_if(nums.begin(), nums.end(), 
                      [](int x) { return x > 3; });

11. 常量表达式 Lambda(C++17+)

使用 constexpr 关键字使 lambda 可以在编译时求值。

cpp 复制代码
constexpr auto add = [](int a, int b) { return a + b; };
static_assert(add(3, 4) == 7, "Error");  // 编译时检查

12. 模板 Lambda(C++20+)

使用模板参数(template <typename T> 的简写)使 lambda 更灵活。

cpp 复制代码
auto lambda = []<typename T>(const T& a, const T& b) { return a + b; };
int sum_int = lambda(1, 2);        // T 推导为 int
double sum_double = lambda(1.5, 2.5);  // T 推导为 double

13. 异常规范(C++17 前)

使用 noexcept 指定 lambda 是否抛出异常。

cpp 复制代码
auto safe_divide = [](double a, double b) noexcept {
    return b != 0 ? a / b : 0;
};

14. 性能考虑

  • Lambda 通常比普通函数指针或 std::function 更高效,因为编译器可内联其代码。
  • 值捕获会复制变量,可能影响性能(尤其是大对象),此时应优先使用引用捕获。

总结

C++ 的匿名函数(Lambda)提供了强大而灵活的语法,使代码更简洁、更易读。掌握捕获列表、参数、返回类型和各种特性(如泛型、捕获初始化)是使用 Lambda 的关键。合理使用 Lambda 可以显著提升 C++ 代码的表达力和效率。

相关推荐
七夜zippoe3 分钟前
为什么 2026 年每个 Java 团队都该懂 AI Agent
java·开发语言·人工智能
举个栗子。5 分钟前
SwarmForge:AI 智能体协同编程框架,让多个 Agent 在隔离工作区并行协作
人工智能·开源·ai编程
znnnk9 分钟前
【Python】GUI 开发从入门到实战(三):PyQt/PySide 进阶之路
开发语言·python·pyqt
AIGC小尼16 分钟前
Windows 本地 AI 漫剧全自动生产线部署完整教程(零基础、全指令、带源码、模型配置、排错方案)
人工智能·windows·ai漫剧
合米AI SOP系统21 分钟前
传统产线如何快速上马落地 AI 防错?合米科技 AI SOP 7天即可上线。
大数据·人工智能·科技
思录Echo21 分钟前
什么决定具身智能的最终走向?多技术路线与落地现实辨析
大数据·人工智能
Despacito100628 分钟前
Java后端性能探查工具速查表
java·开发语言
ShallWeL39 分钟前
Orin 上多模型常驻与显存预算
人工智能·嵌入式硬件·nvidia·orin
xiaohaiAIgeo41 分钟前
【2026年】AI监控加行为分析守护实验室安全
大数据·人工智能·科普知识
IT_陈寒42 分钟前
Python的多线程就是个假把式,我算是体验到了
前端·人工智能·后端