[2.2节]lamda表达式

2.2 lamda表达式

1 基本语法

a. [捕获列表] (参数列表) -> 返回类型{函数体}
例如:auto Add = [](int a, int b) -> int {return a + b;}
一般情况下,编译器会自动推断出返回类型,所以可以不指定。

b. 可以简化为: [捕获列表] (参数列表) {函数体}
例如:auto Add = [](int a, int b) {return a + b;};
在C++11之后,如果Lamba表达式的函数体内有多个return语句且返回类型不一致,编译器无法自动推断的时候,此时必须显式的指定返回类型。
范例1 :

    // 由于函数体内有多个 return 语句,编译器无法自动推断出返回类型,
    // 因此我们使用 -> string 明确指定了返回类型。
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main() {
        auto example = [](int x) -> string {
            if (x > 0) return "Positive";
            else if (x == 0) return "Negative";
            else return "None";
        };
    
        cout << example(5) << endl;
        cout << example(0) << endl;
        cout << example(-15) << endl;
    
        return 0;
    }

范例2:
当出现返回的类型有多种情况的时候:

#include <iostream>
    #include <variant>
    #include <string>
    using namespace std;
    
    int main() {
        auto example = [](int x) -> variant<int, string> {
            if (x > 0) return x;
            else return "None";
        };
    
        auto result1 = example(5);
        auto result2 = example(-5);
    
        if (holds_alternative<int>(result1)) {
            cout << "Result1: " << get<int>(result1) << endl;
        } else {
            cout << "Result1: " << get<string>(result1) << endl;
        }
    
        if (holds_alternative<int>(result2)) {
            cout << "Result2: " << get<int>(result2) << endl;
        } else {
            cout << "Result2: " << get<string>(result2) << endl;
        }
    
        return 0;
    }

这里使用了bool holds_alternative来判断返回的类型是什么。由于 Lambda 表达式有多个 return 语句且返回类型不同,我们必须显式指定返回类型为 variant<int, string>

c. 还可以进一步简化为:[捕获列表] {函数体}

可以进一步忽略参数列表和返回类型,只保留捕获列表和函数体:

auto f = []{ return 1 + 2; };

2 捕获列表

当表达式需要使用外部变量的时候,用捕获列表来传参数,如:

void test3()
{
    int c = 12;
    int d = 30;
    auto Add = [c, d](int a, int b)->int { //捕获列表加入使用的外部变量c,否则无法通过编译
        cout << "d = " << d  << endl;      //这里的c和d都是捕获的值,不是引用,假如c = a会报错
        return c;
    };
    d = 20;
    std::cout << Add(1, 2) << std::endl;
}

这里的[c, d]内有多种符号表示:

  • 如果捕获列表为[&],则表示所有的外部变量都按引用传递给lambda使用;
  • 如果捕获列表为[=],则表示所有的外部变量都按值传递给lambda使用;这里的c和d就是值,对于按值传递的捕获列表,会立即将当前取到的值拷贝一份作为常数,然后将该常数作为参数传递。
  • [this] ,捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限,如果已经使用了 &或者 =, 默认添加此选项。
void test4()
{
    int c = 12;
    int d = 30;
    auto Add = [&c, &d](int a, int b)->int { //捕获列表加入使用的外部变量c,否则无法通过编译
        c = a; // 编译对的
        cout << "d = " << d  << endl;
        return c;
    };
    d = 20;
    std::cout << Add(1, 2) << std::endl;
}

3 lamda表达式的本质

如果希望去修改按值捕获的外部变量,那么应该如何处理呢?这就需要使用mutable选项,mutable修改是lambda表达式就算没有参数也要写明参数列表,并且可以去掉按值捕获的外部变量的只读(const)属性。

int a = 0;
auto f1 = [=] {return a++; };              // error, 按值捕获外部变量, a是只读的
auto f2 = [=]()mutable {return a++; };     // ok 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小马敲马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值