C++:Lambda表达式的含义及用法详解

C++ 中的 Lambda 表达式 是一种轻量级的匿名函数,可以在函数内部定义并作为参数传递给算法或其他函数。它是一种便捷的方式来定义小型函数,不需要单独定义一个函数名。Lambda 表达式在 C++11 引入,并在 C++14 和 C++17 进一步扩展。

Lambda 表达式的基本语法

Lambda 表达式的一般形式为:

[捕获列表](参数列表) -> 返回类型 { 函数体 };

各部分的详细说明:

  1. 捕获列表(capture list): []

    • 用于捕获 lambda 表达式外部作用域的变量,以便在 lambda 内部使用。捕获列表可以指定按值捕获、按引用捕获等方式。
    • 如果不需要捕获外部变量,可以留空。
  2. 参数列表(parameter list): ()

    • 传递给 lambda 表达式的参数,类似于函数参数列表。如果没有参数,可以省略参数名。
  3. 返回类型(return type): ->

    • 用于指定返回类型。如果省略,编译器可以通过函数体中的 return 语句自动推断返回类型。
    • 如果函数体不返回值或只有一条 return 语句,返回类型推断是可选的,通常可以省略 -> 返回类型
  4. 函数体(function body): {}

    • lambda 表达式的具体实现逻辑。

Lambda 表达式的示例

1. 基本示例:无捕获列表,无参数

#include <iostream>

int main() {
    // 定义一个简单的lambda表达式
    auto hello = []() {
        std::cout << "Hello, World!" << std::endl;
    };
    
    // 调用lambda表达式
    hello();
}

输出:

Hello, World!

2. 捕获列表示例

捕获列表用于从外部作用域捕获变量。

  • 按值捕获:拷贝变量的值到 lambda 中使用。
  • 按引用捕获:使用外部变量的引用,在 lambda 中修改外部变量的值。
#include <iostream>

int main() {
    int x = 10;
    int y = 20;
    
    // 按值捕获x,按引用捕获y
    auto lambda = [x, &y]() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
        // x 在这里是只读的,无法修改
        // y 是按引用捕获,可以修改
        y = 30;
    };

    lambda(); // 输出: x: 10, y: 20
    std::cout << "After lambda call, y: " << y << std::endl; // 输出: After lambda call, y: 30
}

输出:

x: 10, y: 20
After lambda call, y: 30

3. 参数和返回值的示例

Lambda 表达式可以接收参数和返回值,和普通函数类似。

#include <iostream>

int main() {
    // 定义一个有参数并且返回值为 int 的 lambda
    auto add = [](int a, int b) -> int {
        return a + b;
    };

    int result = add(5, 10);
    std::cout << "Result: " << result << std::endl;  // 输出: Result: 15
}

如果 lambda 中只有一条 return 语句,且返回值可以推导,则可以省略 -> 返回类型

auto add = [](int a, int b) {
    return a + b;
};

4. 通用捕获方式

C++ 提供一些常用的捕获方式,可以通过符号指定不同的捕获行为:

  • [=]:按值捕获所有外部变量(默认捕获值)。
  • [&]:按引用捕获所有外部变量(默认捕获引用)。
  • [this]:按值捕获当前对象的 this 指针,允许在 lambda 中使用类成员。
  • [=, &var]:按值捕获所有变量,按引用捕获 var
  • [&, var]:按引用捕获所有变量,按值捕获 var

示例:按引用捕获所有变量

#include <iostream>

int main() {
    int x = 10;
    int y = 20;

    // 按引用捕获所有外部变量
    auto lambda = [&]() {
        x = 30;
        y = 40;
    };

    lambda();
    std::cout << "x: " << x << ", y: " << y << std::endl;  // 输出: x: 30, y: 40
}

高级用法

1. Lambda 表达式作为参数传递

Lambda 表达式通常用作算法或函数的参数,例如 std::sort 函数:这一行代码实际上给了 sort 函数一个自定义的比较方式(lambda 表达式),用于比较对象的排序依据。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {3, 1, 4, 1, 5, 9};

    // 使用lambda表达式按降序排序
    std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
        return a > b;
    });

    for (int n : numbers) {
        std::cout << n << " ";  // 输出: 9 5 4 3 1 1
    }
}

2. Lambda 捕获可变变量(mutable 关键字)

默认情况下,按值捕获的变量是不可修改的。如果需要在 lambda 内修改按值捕获的变量,可以使用 mutable 关键字。

#include <iostream>

int main() {
    int x = 10;

    // 捕获x,并在lambda内部修改x
    auto lambda = [x]() mutable {
        x = 20;
        std::cout << "Inside lambda, x: " << x << std::endl;  // 输出: Inside lambda, x: 20
    };

    lambda();
    std::cout << "Outside lambda, x: " << x << std::endl;  // 输出: Outside lambda, x: 10
}

注意:mutable 仅影响 lambda 内的拷贝,原始变量不会改变。

3. Lambda 表达式的类型

Lambda 表达式是匿名的,但它有自己的唯一类型,不能直接声明为普通函数指针。然而,可以使用 std::function 来存储 Lambda 表达式,特别是在返回类型和参数列表匹配的情况下。

#include <iostream>
#include <functional>

int main() {
    std::function<int(int, int)> add = [](int a, int b) {
        return a + b;
    };

    std::cout << "Result: " << add(3, 4) << std::endl;  // 输出: Result: 7
}

总结

C++ 中的 Lambda 表达式提供了一种非常灵活、简洁的方式来定义匿名函数,广泛用于算法和函数对象。关键概念包括:

  • 捕获列表用于访问外部作用域变量。
  • Lambda 可以接收参数、返回值,并在必要时修改捕获变量。
  • 它可以与标准库算法(如 std::sort)配合使用,简化代码。

通过使用 Lambda 表达式,你可以编写出更具表达力和简洁性的代码,尤其是在需要传递短小功能的场景中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值