当前位置:网站首页>lambda表达式

lambda表达式

2022-07-05 00:05:00 DWQY

前言

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

static bool cmp() {
    
...
}
void function() {
    
	...
      sort(A.begin(),A.end(),cmp);
...
}

  使用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

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

原网站

版权声明
本文为[DWQY]所创,转载请带上原文链接,感谢
https://blog.csdn.net/gls_nuaa/article/details/125525121