当前位置: 首页 > article >正文

【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!";
});


http://www.kler.cn/news/342572.html

相关文章:

  • 安卓数据共享
  • Docker 部署 Redis 监控系统实战:Redis Exporter 与 Prometheus 完整配置指南
  • 数学建模算法与应用 第8章 时间序列分析
  • 重学SpringBoot3-集成Redis(七)之分布式限流
  • springboot第75集:kafka,线程,进程,容器化服务,线程池
  • 基于深度学习的复杂器官建模与模拟
  • Linux 安全日志分析及方法
  • 初学java练习题【1】
  • 自然语言处理问答系统:技术进展、应用与挑战
  • 基于STM32 ARM+FPGA+AD的电能质量分析仪方案设计(一)硬件设计
  • 使用Pytorch写简单线性回归
  • 基于STM32设计的生猪健康检测管理系统(NBIOT+OneNet)(240)
  • ubuntu22.04 安装wine9.0 全网首发
  • 编译运行多个c程序,怎么修改VSCode里面的插件Code Runner的配置:
  • 设计模式-行为型-常用-1:观察者模式、模板模式、策略模式
  • Mysql INSERT INTO SELECT 复制语句
  • 《C++编程新探索:实现高效视频拼接算法》
  • springmvc发送邮件的功能怎么集成Spring?
  • 微信小程序不支持font-weight:500
  • MPI错误对照表