C++ 可调用对象总结(二) lambda表达式

前文回顾:
C++ 可调用对象总结(一) 函数对象

lambda

  1. 定义

    一个 lambda 表达式表示一个可调用的代码单元,可以理解为是一个未命名的内敛函数。类似任何函数,一个 lambda 具有返回类型、参数列表和函数体;和普通函数不同, lambda 必须使用尾置返回来指定返回类型。

在这里插入图片描述

①.捕获列表

捕获列表是一个 lambda 所在函数中定义的局部变量的列表,捕获列表能够捕捉上下文中的变量以供 lambda 使用。

捕获列表可以为空,但 [] 不可以省略,编译器依次来判断接下来的代码是否是 lambda 表达式。

②.参数列表

和普通函数的参数列表一致,如果不需要参数传递,则可以连同括号 () 一起省略。lambda 中参数不能有缺省值,也不能有无名参数。

③.mutable

默认情况下,对于一个值被拷贝的变量,lambda 不会改变其值,加上 mutable 修饰符后,可以修改传递进来的拷贝。

在使用 mutable 修饰符时,参数列表部分不可省略,但列表可以为空。

④.返回类型

标识函数返回值的类型,当返回值为 void,或者函数体中只有一处 return 时可用省略。

⑤.函数体

标识函数的实现,内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

函数体不能省略,但函数体可以为空。

  1. 捕获列表

    ①.概念

    一个 lambda 通过将局部变量包含在其捕获列表中来指定将会使用这些变量,只能使用明确指明的变量;变量捕获方式可以传值捕获,也可以传引用捕获。

    ②.按值捕获变量

    在捕获列表中指定变量名字,类似传值的参数,被捕获的变量值将在 lambda 创建时被拷贝。

在这里插入图片描述

③.按引用捕获变量

用 & 引用捕获,一个以引用方式捕获的变量,在 lambda 中被使用时,实际上使用的引用所绑定的对象。

在这里插入图片描述

④.多参数捕获

捕获列表中可以指定捕获多个参数,并且可以为每个参数指定捕获方式。

在这里插入图片描述

⑤.隐式按值捕获

使用 [=] 表示按值捕获 lambda 所在范围内所有可见的局部变量。

在这里插入图片描述

⑥.隐式按引用捕获

使用 [&] 表示按引用方式捕获 lambda 所在范围内所有可见的局部变量。

在这里插入图片描述

⑦.隐式混和捕获

使用 [=,prams] 表示除 xxx 按引用捕获外,其他所有参数按值捕获;使用 [&,prams] 表示除 xxx 按值捕获外,其他所有参数按引用捕获。

在这里插入图片描述

  1. 可变 lambda

    默认情况下 lambda 不会改变按值捕获的变量,如果希望改变一个被拷贝的值,必须使用 mutable 关键字,且参数列表不能省略。

在这里插入图片描述

  1. 指定返回类型

    如果一个 lambda 函数体包含了 return 之外的任何语句,则编译器假定返回类型为 void,此时我们必须指定返回值类型。

在这里插入图片描述

  1. lambda是函数对象

    定义一个 lambda ,编译器会生成一个与 lambda 对应的新的类类型。当向一个函数传递一个 lambda 时,同时定义了一个新类型和该类型的一个对象,生成的类包含所捕获变量对应的数据成员,数据成员在类创建时被初始化。

    int sum = 0;
    std::vector<int> vec = { 1,2,3,4,5 };
    std::for_each(begin(vec), end(vec), [&sum](int x){sum += x;});
    

    上述代码被编译器翻译后变为:

    class lambda_b
    {
    private:
        int* m_pSum;
    public:
        lambda_b(int* pSum)
        {
            m_pSum = pSum;
        }
    
        void operator()(int x) const 
        {
            *m_pSum += x;
        }
    };
    
    int sum = 0;
    std::vector<int> vec = { 1,2,3,4,5 };
    std::for_each(begin(arry), end(arry), lambda_b(&sum));
    
  2. lambda 使用

    lambda 表达式实际为一个函数对象,可以把匿名函数保存在变量当有名函数来使用。

    ①.使用 auto 保存

    int a = 1;
    int b = 2;
    //使用 auto 保存 lambda 
    auto func = [a, &b](int c)mutable ->int { b = a + c; return a; };
    //做有名函数使用	
    cout << b << "  "<< func(10) << endl;
    

    ②.函数指针保存

    当 lambda 的捕获外部变量列表为空时,可使用普通函数指针来保存。

    //使用函数指针保存 lambda 
    int(*func1)(int) = [](int x) {return x; };
    //函数调用
    int a = func1(20);
    

    ③.使用 std::function 模板类型

    #include <functional>
    std::function<float(int,float)> fun1 = [](int x, float y) { return x + y; };
    float a = fun1(12,1.2);//函数调用
    

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值