12.C++11新特性之Lambda表达式

        Lambda 表达式是 C++11 引入的一项重要特性,它提供了一种简洁的方式来创建匿名函数对象,可用于临时的、一次性的函数需求,尤其在使用标准库算法时非常方便。以下从语法、捕获列表、参数列表、返回类型、函数体、使用场景和优缺点几个方面详细介绍 Lambda 表达式。

1.基本语法

        Lambda 表达式的基本语法如下:

[capture list] (parameter list) -> return type { function body }
  • 捕获列表(capture list):用于指定 Lambda 表达式可以访问的外部变量。
  • 参数列表(parameter list):与普通函数的参数列表类似,用于传递参数给 Lambda 表达式。
  • 返回类型(return type):可省略,编译器通常能自动推导返回类型。
  • 函数体(function body):包含 Lambda 表达式要执行的代码。

2.捕获列表

        捕获列表用于指定 Lambda 表达式可以访问的外部变量,有以下几种捕获方式:

  • 值捕获

        通过值的方式捕获外部变量,Lambda 表达式会在创建时复制这些变量的值。

#include <iostream>

int main() {
    int x = 10;
    auto lambda = [x]() {
        std::cout << "Captured value: " << x << std::endl;
    };
    lambda();
    return 0;
}

        在上述代码中,[x] 表示以值的方式捕获变量 x,Lambda 表达式内部使用的是 x 的副本

  • 引用捕获

        通过引用的方式捕获外部变量,Lambda 表达式会引用这些变量,而不是复制它们的值。

#include <iostream>

int main() {
    int x = 10;
    auto lambda = [&x]() {
        x = 20;
        std::cout << "Modified value: " << x << std::endl;
    };
    lambda();
    std::cout << "Value outside lambda: " << x << std::endl;
    return 0;
}

        这里 [&x] 表示以引用的方式捕获变量 x,Lambda 表达式内部对 x 的修改会影响到外部的 x

  • 混合捕获

        可以同时使用值捕获和引用捕获

#include <iostream>

int main() {
    int x = 10;
    int y = 20;
    auto lambda = [x, &y]() {
        std::cout << "x: " << x << std::endl;
        y = 30;
        std::cout << "Modified y: " << y << std::endl;
    };
    lambda();
    std::cout << "y outside lambda: " << y << std::endl;
    return 0;
}

        在这个例子中,x 以值的方式捕获,y 以引用的方式捕获。

  • 隐式捕获

        可以使用 [=] 表示以的方式隐式捕获所有外部变量,使用 [&] 表示以引用的方式隐式捕获所有外部变量

#include <iostream>

int main() {
    int x = 10;
    int y = 20;
    auto lambda1 = [=]() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
    };
    auto lambda2 = [&]() {
        x = 30;
        y = 40;
        std::cout << "Modified x: " << x << ", Modified y: " << y << std::endl;
    };
    lambda1();
    lambda2();
    std::cout << "x outside lambda: " << x << ", y outside lambda: " << y << std::endl;
    return 0;
}

3.参数列表

        参数列表与普通函数的参数列表类似,用于传递参数给 Lambda 表达式。

#include <iostream>

int main() {
    auto lambda = [](int a, int b) {
        return a + b;
    };
    int result = lambda(3, 5);
    std::cout << "Result: " << result << std::endl;
    return 0;
}

        在这个例子中,Lambda 表达式接受两个整数参数 a 和 b,并返回它们的和。

4.返回类型

        返回类型通常可以省略,编译器会自动推导。但在某些情况下,也可以显式指定返回类型

#include <iostream>

int main() {
    auto lambda1 = [](int a, int b) {
        return a + b;  // 编译器自动推导返回类型为 int
    };
    auto lambda2 = [](int a, int b) -> double {
        return static_cast<double>(a) / b;  // 显式指定返回类型为 double
    };
    std::cout << "Result 1: " << lambda1(3, 5) << std::endl;
    std::cout << "Result 2: " << lambda2(3, 5) << std::endl;
    return 0;
}

5.函数体

        函数体包含 Lambda 表达式要执行的代码,与普通函数的函数体类似。

#include <iostream>

int main() {
    auto lambda = []() {
        std::cout << "Hello, Lambda!" << std::endl;
    };
    lambda();
    return 0;
}

6.使用场景

  • 作为标准库算法的谓词

        Lambda 表达式可以作为标准库算法(如 std::sort、std::find_if 等)的谓词,使代码更加简洁。

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

int main() {
    std::vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
    // 使用 Lambda 表达式对向量进行排序
    std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
        return a < b;
    });
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    return 0;
}
  • 异步编程

        在异步编程中,Lambda 表达式可以作为回调函数使用。

#include <iostream>
#include <thread>

// 定义一个异步操作函数,该函数接受一个无参数、无返回值的函数对象作为回调函数
void asyncOperation(std::function<void()> callback) {
    // 创建一个新的线程来执行异步操作
    std::thread([callback]() {
        // 模拟一个耗时的异步操作,这里让线程休眠2秒
        std::this_thread::sleep_for(std::chrono::seconds(2));
        // 当异步操作完成后,调用传入的回调函数
        callback();
    // 分离线程,使得该线程在后台独立运行,主线程不需要等待它结束
    }).detach();
}

int main() {
    // 调用异步操作函数,并传入一个Lambda表达式作为回调函数
    asyncOperation([]() {
        // 当异步操作完成后,输出提示信息
        std::cout << "Async operation completed." << std::endl;
    });

    // 主线程继续执行,输出提示信息
    std::cout << "Main thread continues..." << std::endl;

    // 为了确保主线程不会过早结束,让主线程休眠3秒
    // 这样可以保证异步操作有足够的时间完成并执行回调函数
    std::this_thread::sleep_for(std::chrono::seconds(3));

    // 程序正常结束,返回0
    return 0;
}

        这段代码的主要功能是模拟一个异步操作,在一个新的线程中执行耗时任务,当任务完成后调用回调函数。主线程不会等待异步操作完成,而是继续执行后续代码。为了避免主线程过早结束,主线程会休眠一段时间,确保异步操作有足够的时间完成。

7.优缺点

  • 优点

简洁性:可以在需要的地方直接定义函数,无需额外定义命名函数,使代码更加简洁。
灵活性:可以方便地捕获外部变量,根据不同的上下文动态调整行为。
可读性:在一些简单的场景下,使用 Lambda 表达式可以使代码的意图更加清晰。

  • 缺点

复杂 Lambda 表达式可读性降低:如果 Lambda 表达式的函数体较为复杂,会使代码的可读性降低。
调试困难:由于 Lambda 表达式是匿名的,在调试时可能会增加一定的难度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值