C++11/14介绍(三)——语言运行期的强化(一)

26 篇文章 0 订阅

Lambda表达式

  • lambda表达式的基本语法如下:

    [捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型{
        //函数体
    }
    

    捕获列表可以理解为参数的一种类型,lambda表达式内部函数体在默认情况下是不能够使用函数体外部的变量的,这时候捕获列表可以起到传递外部数据的作用。根据传递的行为,捕获列表分为以下几种。

    • 值捕获

      void learn_lambda_func_1() {
          int value_1 = 1;
          auto copy_value_1 = [value_1] {
              return value_1;
          };
          value_1 = 100;
          auto stored_value_1 = copy_value_1();
          // 这时, stored_value_1 == 1, 而 value_1 == 100.
          // 因为 copy_value_1 在创建时就保存了一份 value_1 的拷贝
          cout << "value_1 = " << value_1 << endl;
          cout << "stored_value_1 = " << stored_value_1 << endl;
      }
      

      与参数传值类似,值捕获的前期是变量可以拷贝,不同之处在于,被捕获的变量在lambda表达式被创建时拷贝,而非调用时才拷贝。

    • 引用捕获

      void learn_lambda_func_2() {
          int value_2 = 1;
          auto copy_value_2 = [&value_2] {
              return value_2;
          };
          value_2 = 100;
          auto stored_value_2 = copy_value_2();
          // 这时, stored_value_2 == 100, value_1 == 100.
          // 因为 copy_value_2 保存的是引用
          cout << "value_2 = " << value_2 << endl;
          cout << "stored_value_2 = " << stored_value_2 << endl;
      }
      

      与引用传参类似,引用捕获保存的是引用,值会发生变化。

    • 隐式捕获

      手动书写捕获列表有时候是非常复杂的,这种机械性的工作可以交给编译器来处理,这时候可以在捕获列表中写一个 &= 向编译器声明采用 引用捕获或者值捕获.

      总结一下,捕获提供了lambda 表达式对外部值进行使用的功能,捕获列表的最常用的四种形式可以是:

      • [] 空捕获列表
      • [name1, name2, …] 捕获一系列变量
      • [&] 引用捕获, 让编译器自行推导捕获列表
      • [=] 值捕获, 让编译器执行推导应用列表
    • 表达式捕获(C++14)

      void learn_lambda_func_3(){
          auto important = std::make_unique<int>(1);
          auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int {
              return x+y+v1+(*v2);
          };
          std::cout << "add(3, 4) = " << add(3, 4) << std::endl;
      }
      

      在上面的代码中,important 是一个独占指针,是不能够被捕获到的,这时候需要将其转移为右值,在表达式中初始化。 C++14允许捕获的成员用任意的表达式进行初始化,这就允许了右值的捕获,被声明的捕获变量类型会根据表达式进行判断,判断方式与使用 auto 本质上是相同的。

    • 泛型lambda(C++14)

      void learn_lambda_func_4(){
          auto generic = [](auto x, auto y) {
              return x+y;
          };
      
          std::cout << "generic(1,2) = " << generic(1, 2) << std::endl;
          std::cout << "generic(1.1,2.2) = " << generic(1.1, 2.2) << std::endl;
      }
      

      auto 关键字不能够用在参数表里,这是因为这样的写法会与模板的功能产生冲突。但是 Lambda 表达式并不是普通函数,所以 Lambda 表达式并不能够模板化。这就为我们造成了一定程度上的麻烦:参数表不能够泛化,必须明确参数表类型。幸运的是,这种麻烦只存在于 C++11 中,从 C++14 开始,Lambda 函数的形式参数可以使用 auto 关键字来产生意义上的泛型

  • 参考:C++ 11/14 高速上手教程 - 语言运行期的强化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值