C++ 的 lambda 表达式是一种匿名函数对象

C++ 的 lambda 表达式是一种匿名函数对象,可以在代码中直接定义和使用。它们特别适用于需要传递函数作为参数的场景,例如在算法中使用自定义比较函数,或者在异步编程中传递任务。以下是对 lambda 表达式的详细解释:

1. 基本语法

cpp 复制代码
[捕获列表](参数列表) -> 返回类型 {
    // 函数体
}

捕获列表

  • 值捕获[x] 将变量 x 按值捕获。
  • 引用捕获[&x] 将变量 x 按引用捕获。
  • 隐式捕获[=] 捕获所有外部变量按值,[&] 捕获所有外部变量按引用。
  • 混合捕获[this, &x] 同时捕获 this 指针和变量 x 的引用。

参数列表

  • 类似普通函数的参数列表,可以为空。

返回类型

  • 可以省略,编译器会自动推断。
  • 如果函数体中有多个 return 语句,并且返回类型不同,编译器可能会报错。

函数体

  • 包含函数的逻辑。

2. 示例代码

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

int main() {
    // 定义一个简单的 lambda 表达式
    auto add = [](int a, int b) -> int {
        return a + b;
    };

    std::cout << "1 + 2 = " << add(1, 2) << std::endl;

    // 捕获外部变量
    int x = 10;
    auto multiply = [x](int y) -> int {
        return x * y;
    };

    std::cout << "10 * 3 = " << multiply(3) << std::endl;

    // 捕获外部变量并修改
    int z = 5;
    auto increment = [&z]() -> void {
        z++;
    };

    std::cout << "Before increment: " << z << std::endl;
    increment();
    std::cout << "After increment: " << z << std::endl;

    // 在算法中使用 lambda 表达式
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::for_each(vec.begin(), vec.end(), [](int n) {
        std::cout << n * 2 << " ";
    });

    return 0;
}

3. 捕获列表的详细解释

值捕获

cpp 复制代码
int x = 5;
auto lambda = [x]() {
    x = 10; // 修改捕获的值
};
lambda();
std::cout << x << std::endl; // 输出 5,因为 x 是按值捕获的

引用捕获

cpp 复制代码
int x = 5;
auto lambda = [&x]() {
    x = 10; // 修改捕获的引用
};
lambda();
std::cout << x << std::endl; // 输出 10,因为 x 是按引用捕获的

隐式捕获

cpp 复制代码
int x = 5;
auto lambda = [=]() {
    std::cout << x << std::endl; // 按值捕获 x
};
cpp 复制代码
int x = 5;
auto lambda = [&]() {
    std::cout << x << std::endl; // 按引用捕获 x
};

混合捕获

cpp 复制代码
int x = 5;
int y = 10;
auto lambda = [x, &y]() {
    std::cout << x << " " << y << std::endl;
    y = 20; // 修改 y 的值
};
lambda();
std::cout << x << " " << y << std::endl; // 输出 5 20

4. 返回值的详细解释

自动推断返回值

cpp 复制代码
auto lambda = [](int a, int b) {
    return a + b; // 返回值类型推断为 int
};

显式指定返回值

cpp 复制代码
auto lambda = [](int a, int b) -> int {
    return a + b; // 显式指定返回值类型为 int
};

5. 高级用法

使用Lambda表达式递归

cpp 复制代码
auto factorial = [](int n) -> int {
    if (n <= 1) return 1;
    return n * factorial(n - 1); // 错误,因为 capture-by-reference 不支持自我调用
};

// 为了支持递归,可以使用 y-combinator 或捕获自身
auto factorial = [&](int n) -> int {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
};

使用Lambda表达式绑定成员函数

cpp 复制代码
class MyClass {
public:
    int value = 0;
    void SetValue(int v) {
        value = v;
    }
};

MyClass obj;
auto lambda = [obj]() {
    obj.SetValue(10); // 调用成员函数
};

使用Lambda表达式进行完美转发

cpp 复制代码
template<typename T>
auto lambda = [](T&& arg) {
    func(std::forward<T>(arg)); // 完美转发
};

6. 总结

C++ 的 lambda 表达式是一种非常灵活的工具,可以简化代码并提高可读性。通过捕获列表,lambda 表达式可以在不同的作用域中访问变量,并且可以通过值或引用的方式捕获这些变量。通过显式指定返回值类型,也可以更精确地控制函数行为。

相关推荐
乌萨奇也要立志学C++38 分钟前
【C++详解】哈希表概念与实现 开放定址法和链地址法、处理哈希冲突、哈希函数介绍
c++·哈希算法·散列表
Forward♞1 小时前
Qt——网络通信(UDP/TCP/HTTP)
开发语言·c++·qt
青草地溪水旁2 小时前
`lock()` 和 `unlock()` 线程同步函数
linux·c++·c
重启的码农2 小时前
Windows虚拟显示器MttVDD源码分析 (3) 驱动回调与入口点 (WDF/IddCx Callbacks)
c++·windows·操作系统
重启的码农2 小时前
Windows虚拟显示器MttVDD源码分析 (4) 间接设备上下文 (IndirectDeviceContext)
c++·windows·操作系统
重启的码农2 小时前
Windows虚拟显示器MttVDD源码分析 (2) EDID与显示器模拟
c++·windows·操作系统
重启的码农3 小时前
Windows虚拟显示器MttVDD源码分析 (1) 配置与设置管理
c++·windows·操作系统
秦jh_3 小时前
【MySQL】基本查询
linux·数据库·c++·mysql
刃神太酷啦3 小时前
Linux 常用指令全解析:从基础操作到系统管理(1w字精简版)----《Hello Linux!》(2)
linux·运维·服务器·c语言·c++·算法·leetcode
颇有几分姿色3 小时前
Java 图像处理传 JNI 到 C++(OpenCV):两种高效实现方式对比
java·c++·图像处理