• lambda表达式


    前言

      第一次接触lambda表达式还是在做leetcode的时候,有一种场景使用lambda表达式特方便,代码如下:

    static bool cmp() {
    ...
    }
    void function() {
    	...
          sort(A.begin(),A.end(),cmp);
    ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

      使用STL的sort()时,要自定义排序方法。这个时候如果排序策略中要使用function()函数中的局部变量就会特别麻烦。而使用lambda表达式就可以直接进行参数传递。当然这只是lambda表达式的冰山一角,这篇文章会更详细的介绍一下,希望这篇文章能够说明白几个问题:
      1.lambda表达式是什么以及如何使用?
      2.lambda表达式使用时的一些原理。

    因为笔者常用C++,所以就使用C++作为举例的语言啦~

    1.什么是lambda表达式?

      lambda表达式可理解为匿名的内联函数,内联函数就是在声明时直接进行定义了,一般有限制条件,要求函数体比较短。匿名的含义就是不需要专门为lambda表达式专门写一个函数名。

      lambda函数主要有三个优点:
      1)方便,可以随手定义短小精悍的函数。定义距离近
      2)不用想函数名
      3)定义立即执行,调用速度快,没有中间一些开销

    2.如何使用lambda表达式?

      先来看看lambda表达式的语法:[capture list](parameter list)->return type{function body}
      主要有四部分,各部分详细定义如下:
      capture list:捕获列表,lambda所在函数中定义的局部变量列表
      parameter list:参数列表
      return type:函数返回类型
      function body:函数体
      与常规函数相比,参数列表,返回类型,函数体都是比较熟悉了。那什么是捕获列表呢?这个稍后再提。注意返回类型的位置,不是在开头,这个源于lambda表达式使用尾置返回类型。

      再举个实例(这个全都有):[](ListNode *x, ListNode *y)->bool {return x->val > y->val;}
      虽然有四个部分,实际上参数列表和返回类型可忽略,但捕获列表和函数体必须存在

      都是函数,和与普通函数的不同之处在哪里呢?
      1)lambda表达式不能有默认参数,实参形参数目保持一致
      2)所有参数必须有参数名
      3)不支持可变参数
      其他的就当结论了,第一条下面会解释一下

    3.lambda表达式中使用的一些原理

      上面留了一个捕获列表的概念,我觉得这个的使用算是lambda表达式的重要环节之一。
      如果没有捕获列表[],lambda表达式函数体中只能使用参数列表中变量,而没办法使用外层函数的局部变量。不过把局部变量放在捕获列表中,lambda表达式就可以使用。

      lambda表达式的捕获方式可以从两个角度看:
      第一个角度是:引用捕获、值捕获
      第二个角度是:普通捕获 隐式捕获 混合捕获

      首先介绍下各自的概念,引用捕获就是传递的是变量的引用,值捕获传递的是变量的拷贝值。类比于参数传递,很容易明白的。显示捕获就是传递具体的变量名,隐式捕获就是用一个标志代表传递所有的。具体落实到使用中的是下面这样的:
      [] 空
      [变量] 只传递变量 值捕获
      [=] 全部实体 值捕获
      [&] 全部引用 引用捕获
      [&,变量名] 变量名值捕获 其余变量引用捕获
      [=,变量名] 变量名引用捕获,其余变量值捕获

      普通捕获:[变量名]
      隐式捕获 :[=] [&]
      混合方式捕获: [=,变量名] [&,变量名]

      有几个重点需要强调:
      1)值捕获中,被值捕获的在lambda表达式创建的时候就拷贝
      2)使用引用捕获时捕获一个变量时,就必须确保被引用的对象在lambda执行的时候是存在的
      3)值捕获中如果想要修改捕获列表中的某个变量值,需要加上mutable,语法就变成:[capture list] (parameter list) mutable -> return type {function body}
      4)上面说返回类型可以省略,但是有条件的:1)返回值是void 2)函数体中只有return一句,编译器可以自行推断

      再深挖下原理,解释一下上面留的:lambda表达式中为何必须要有实参?
      当然需要实参的前提是参数列表有东西哈。原因在于lambda表达式的本质是构造类,构造的类类没有默认构造函数,赋值运算符和默认析构函数。因为没有默认构造函数,在带参函数时,必须提供实参才能正常构造。并且在类的构造中会对捕获的变量进行处理,通过值捕获的会把参数作为成员变量,而引用捕获,参数不会作为成员变量。找个一个实例参考一下:
    在这里插入图片描述
    实例来源:https://blog.csdn.net/sgh666666/article/details/89000215

    因作者水平有限,如有错误之处,请在下方评论区指正,谢谢!

  • 相关阅读:
    实用的 “edge://flags“
    Python Connect SQLServer 2008
    嵌入式开发学习之--用蜂鸣器来传递摩斯码
    OpenCV实现人脸关键点检测
    全网最牛自动化测试框架系列之pytest(5)-断言
    壳聚糖/纳米金水凝胶/纳米木质素/掺杂二硫化钼/微米级Ag2O2掺杂壳聚糖水凝胶的制备研究
    七、Kafka-Kraft 模式
    图的基本概念
    (附源码)app智能手机的微课程学习系统 毕业设计 100909
    pix2tex - LaTeX OCR 安装使用记录
  • 原文地址:https://blog.csdn.net/gls_nuaa/article/details/125525121