【cpp】 lambda 表达式常用笔记

Outline

整理了课程笔记和收集的资料, 不断更新

  • 总结 lambda表达式
    函数指针 仿函数 等使用集合

lambda

基本

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

捕获列表:在C++中,捕获列表定义了lambda表达式可以访问的外部变量。
参数列表:可以为空或包含多个参数,类似于函数的参数。
返回类型:C++11中可以省略,编译器会自动推断;C++14及更高版本可以使用auto作为返回类型。注意: 某些情况必须指定 见AAA
函数体:lambda函数的执行逻辑。

AAA
1 由于 x > 0 和 else 分支的返回类型不同(int 和 double),编译器无法自动推断出统一的返回类型。此时,必须显式指定返回类型

auto f = [](int x) -> double {
    if (x > 0)
        return x;  // 这里会将int提升为double
    else
        return 0.5;
};

2 a / b 的返回值是整数除法的结果(整型),但我们可能想要浮点数结果。

auto divide = [](int a, int b) -> double {
    return static_cast<double>(a) / b;
};

3 返回类型为复杂类型或引用 (如迭代器、指针、引用等)

std::vector<int> vec = {1, 2, 3, 4, 5};
auto getElement = [&](int index) -> int& {
    return vec[index];  // 返回对vector元素的引用
};

捕获列表

捕获列表决定了 lambda 表达式如何访问作用域外的变量
1 按值捕获(=):捕获外部变量的副本,不能修改原始变量

int x = 10;
auto f = [x]() { return x + 1; };  // 按值捕获x
std::cout << f();  // 输出11,x仍为10

2 按引用捕获(&):捕获外部变量的引用,可以修改外部变量的值

int x = 10;
auto f = [&x]() { x += 1; };
f();
std::cout << x;  // 输出11,x被修改

3捕获所有外部变量(按值[=]或按引用[&]):可以同时捕获所有外部变量

int x = 10;
int y = 5;
auto f = [=]() { return x + y; };  // 按值捕获所有变量
auto g = [&]() { x += y; };        // 按引用捕获所有变量

4 混合捕获:既可以按值捕获一部分变量,又可以按引用捕获另一部分变量

int x = 10, y = 20;
auto f = [x, &y]() { return x + y; };  // x按值,y按引用

关于捕获范围

无论是 [=] 还是 [&],捕获的外部变量范围仅限于在 lambda 表达式定义时在当前作用域中可见的变量。包括:

  • 局部变量
  • 函数参数
  • 静态局部变量
  • 全局变量
  • 类的成员变量(如果 lambda 定义在类的方法内,则也可以捕获 this 指针)例子如下
class MyClass {
public:
    int a = 10;

    void foo() {
        auto lambda = [this]() {
            std::cout << "a: " << a << std::endl;  // 可以访问成员变量 a
        };
        lambda();
    }
};

在 lambda 表达式中访问类的成员变量(如 a),其实等同于访问 this->a。当捕获 this 时,lambda 内部实际上是通过 this 指针来访问类的成员变量的。
虽然在代码中显式写的是 a,但实际上编译器隐式理解为 this->a。如果不捕获 this,将无法在 lambda 中访问非静态的成员变量。

auto lambda = []() {
    std::cout << "a: " << a << std::endl;  // 错误:无法直接访问 a
};

在这里插入图片描述

捕获的范围不包括临时变量或表达式结果。
默认情况下,lambda 不会捕获 this 指针,除非显式捕获。例如,通过 [=, this] 或 [&] 可以捕获 this 指针。

使用

1 基本计算

auto add = [](int a, int b) { return a + b; };
std::cout << add(2, 3);  // 输出5

2 与标准库配合 泛形算法

std::vector<int> vec = {5, 2, 8, 1, 3};
std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; });

3捕获外部变量的高级用法
按值捕获的可修改性(C++14特性):在C++14中,可以通过在捕获列表中使用mutable关键字允许修改按值捕获的变量。

int x = 10;
auto f = [x]() mutable { x += 5; return x; };
std::cout << f();  // 必须有mutable

在这里插入图片描述

int x = 10;
auto f = [z = x + 5]() { return z; };  // 捕获x+5的值
std::cout << f();  // 输出15

4 暂时没有试过:
Lambda 表达式与并行编程

auto task = std::async([]() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Task completed!";
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值