C++——lambda表达式

Lambda 表达式是 C++11 引入的匿名函数(没有名字的临时函数),主要用于简化代码、就地定义短小函数、配合算法 / 回调使用,是现代 C++ 开发必备语法。

一、基础语法

1.完整语法格式

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

极简记忆版:

  • [] 捕获列表:必写,用来 “抓取” 外部变量供函数体使用
  • () 参数列表:可选,和普通函数参数一样
  • -> type 返回值:可选,编译器能自动推导时可省略
  • {} 函数体:必写,存放执行逻辑

2.省略写法

从右向左依次省略,只有省略返回值类型才能省略参数列表

二、核心用法

1. 无参无捕获

不需要外部变量,也没有参数:

#include <iostream>
using namespace std;

int main() {
    // 定义并直接调用 Lambda
    []() { cout << "Hello Lambda!" << endl; }();
    
    // 赋值给变量,后续调用
    auto func = [] { cout << "无参简化版" << endl; };
    func();
    return 0;
}

2. 带参数

// 计算两数之和
auto add = [](int a, int b) { return a + b; };
cout << add(3, 5) << endl; // 输出 8

3.带返回值

  • 简单逻辑:编译器自动推导返回值,不用写 ->
  • 复杂逻辑:建议显式声明(更清晰)
// 自动推导
auto max = [](int a, int b) { return a > b ? a : b; };

// 显式声明返回值 int
auto sum = [](double a, double b) -> int { return a + b; };

三、捕获列表 []

全局变量,静态成员不存在捕获概念,若 Lambda 内部有同名局部变量 / 形参,内部变量优先(局部遮蔽全局)。

局部变量、函数形参存在捕获概念;Lambda 只能捕获:与 Lambda 同作用域、且在 Lambda 定义语句之前声明的变量。

如果调用两次,捕获列表只在定义时参与运算,只进行一次

#include <iostream>
using namespace std;

// 全局变量:无捕获概念
int num = 100;

void test(int param)  // param:函数形参,存在捕获概念
{
    // 局部变量:存在捕获概念,定义在lambda之前
    int local1 = 200;

    // Lambda定义处:只能捕获同作用域、定义前的局部/形参
    auto lambda = [param, local1]() {
        // 1. 内部定义同名局部变量,遮蔽全局num
        int num = 999;
        cout << "Lambda内部同名num:" << num << endl;  // 输出999,内部优先,遮蔽全局

        // 2. 捕获到的形参、局部变量正常使用
        cout << "捕获的形参param:" << param << endl;
        cout << "捕获的局部local1:" << local1 << endl;
    };

    // 定义在Lambda之后的局部变量:不能被捕获
    int local2 = 300;
    // auto err = [local2](){};  // 编译报错:local2在lambda定义后,无法捕获

    lambda();
}

int main()
{
    test(50);
    return 0;
}

1.值捕获 [=] [x]

用了才会建立副本,相当于创建副本,Lambda 内部用的是拷贝,和外部变量无关。

值捕获完只可读,不可写

去常性:

auto lam = [a]() mutable {
    a = 100;   // 成功
};
  • 加 mutable 改的是副本

  • 外面的 a 依然不变

  • 引用捕获 [&a] 不用加 mutable,本来就能改

2.引用捕获 [&] [&x]

不创建副本,直接用外部变量本身。

可读,可改

3.析构顺序

值捕获:拷贝入栈按书写顺序,析构逆序;

引用捕获:不入栈、不析构,跟随外部变量。

4.捕获格式(8种)

格式含义
[]不捕获任何变量
[x]值捕获 x(拷贝副本,默认 const 只读)
[&x]引用捕获 x(直接用原变量,可修改)
[=]全部值捕获:当前作用域所有局部 / 形参都值捕获
[&]全部引用捕获:当前作用域所有局部 / 形参都引用捕获
[=, &x]默认全部值捕获,唯独 x 引用捕获
[&, x]默认全部引用捕获,唯独 x 值捕获
[this]捕获类的 this 指针,访问类成员

四、泛型捕获

这是 C++14 最重要的 Lambda 升级之一

1.核心格式

[变量名 = auto 表达式]

作用:在捕获列表里,让编译器自动推导捕获变量的类型,和普通 auto 一样。

五、类的成员捕获

异类对象可捕获,异类成员不可捕;

本类成员靠 this,访问必须走对象。

1.核心总规则

成员变量 / 成员函数,不能直接捕获(不能写 [m_val])

只能捕获两种:

[this]:捕获对象指针,操作原对象(C++11 起)

[*this]:捕获整个对象副本,操作副本(C++17 起)

函数内局部变量、形参正常捕获;全局变量不用捕获

#include <iostream>
using namespace std;

// 另一个类
class B {
public:
    int b_val = 200;
};

// 本类
class A {
public:
    int a_val = 100;

    // 形参是另一个类B的对象
    void func(B b_obj, B& b_ref) 
    {
        int x = 10;

        // 捕获:this(本类)、b_obj(另一个类值捕获)、b_ref(另一个类引用捕获)、x(局部)
        auto lam = [this, b_obj, &b_ref, x]() mutable {
            // 访问本类成员
            a_val = 111;

            // 访问另一个类B的成员(必须通过对象)
            b_obj.b_val = 222;  // 修改副本
            b_ref.b_val = 333;  // 修改原B对象

            // 错误:不能直接捕获另一个类的成员
            // auto err = [b_obj.b_val](){};
        };

        lam();

        cout << "本类A:" << a_val << endl;
        cout << "另一个类B原对象:" << b_ref.b_val << endl;
    }
};

int main()
{
    A a;
    B b;
    a.func(b, b);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值