C++仿函数和Lambda表达式

C++仿函数和Lambda表达式

  • 一,普通函数
  • 二,仿函数
  • 三,Lambda表达式
  • 四,Lambda外部变量捕获

     在使用algorithm算法库中的很多函数时,最后一个参数都是需要传入一个函数指针,当对数组或者容器数据遍历时,通过函数指针指向的函数内部的逻辑处理进行过滤,筛选出符合条件的值并进行结果统计或返回。第三个参数的实现形式,从最开始的普通函数,再到函数对象,最后到C11支持的Lambda表达式,本文分别介绍这三种用法。

一,普通函数

     普通函数就是一个常规的函数,函数名即函数指针。以下面一个简单的例子为例:
C++仿函数和Lambda表达式_第1张图片
     定义一个Stock结构体,内部有两个成员变量_name(股票名称),_code(股票diamante),声明一个vector容器,存放了几个Stock结构,然后调用std::find_if查找符合条件的股票,很常见的写法就是上面这个bool IsFitted(const Stock& stk)函数。
     但是,如果查找的股票名称和股票代码不是固定的呢,那么就需要考虑将它作为一个变量:(应该没有小伙伴想到把函数再新增一个参数吧。。。)
1),作为局部变量,只能在这个函数内部修改,不能在调用的地方传入,可拓展性不强
2),作为全局变量,后续的新增参数都只能作为全局变量,维护起来不方便。
3),成员变量,将需要比较的值作为成员变量保存起来,可以作为类构造函数的参数进行传参,可拓展性强,且易维护。这就出现了仿函数。

二,仿函数

     仿函数就是使一个类的使用看上去像一个函数。其实现就是类中重载了()操作符,这个类就有了类似函数的行为,就是一个仿函数类了。我们对上面的例子进行改写如下:
C++仿函数和Lambda表达式_第2张图片
     CFitted类构造函数作为传参用,并且重载了()运算符,那么是可以直接声明一个该类的类对象,直接作为函数指针来使用的。此时,调用处改写为:
C++仿函数和Lambda表达式_第3张图片
     此时参数是由外部传入的,达到了可控的目的。

三,Lambda表达式

     随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法, 都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。因此,在C11语法中出现了Lambda表达式。
     利用Lambda表达式,可以方便的定义和创建匿名函数。对于C++这门语言来说来说,“Lambda表达式”或“匿名函数”这些概念听起来好像很深奥,但很多高级语言在很早以前就已经提供了Lambda表达式的功能,如C#,Python等。
Lambda表达式完整的格式声明如下:

[capture list] (params list) mutable exception-> return type { function body }

     它主要由以下四个部分组成:
1),capture list:捕获外部变量列表
2),params list:形参列表
3),mutable:标明是否可以修改捕获的变量
4),return type:返回类型
5),function body:函数体

     Lambda表达式的格式并不是固定不变的,我们可以省略某些部分来声明一个“不完整”的Lambda表达式。比如:正常使用中,我们很少会用到return type,因为Lambda表达式可以根据function body中的返回值来判断返回类型。省略params list时,也就相当于一个普通的无参函数。
     对上述例子用Lambda表达式改造如下:
C++仿函数和Lambda表达式_第4张图片
     在Lambda表达式中,我们捕获了外部变量stCmp,这里是值捕获,然后将stCmp和每一个函数形参Stock st进行比较。Stock st是在find_if中遍历容器的每一个值时传进去的。
C++仿函数和Lambda表达式_第5张图片

四,Lambda外部变量捕获

     Lambda表达式通过在最前面的方括号[]来明确指明其内部可以访问的外部变量,这一过程也称过Lambda表达式“捕获”了外部变量。
C++仿函数和Lambda表达式_第6张图片
1,值捕获
     值捕获和参数传递中的值传递类似,被捕获的变量的值在Lambda表达式创建时通过值拷贝的方式传入,因此随后对该变量的修改不会影响影响Lambda表达式中的值。
C++仿函数和Lambda表达式_第7张图片
     输出结果如下:
在这里插入图片描述
2,引用捕获
     使用引用捕获一个外部变量,只需要在捕获列表变量前面加上一个引用说明符&。引用捕获结合mutable说明符,可以对外部变量进行修改。
将上述的Lambda表达式改写为:
C++仿函数和Lambda表达式_第8张图片
     此时,捕获变量加了&,输出结果如下:
在这里插入图片描述

3,=和&隐式捕获
     =和&允许Lambda表达式捕获所有外部变量,=是值捕获,&是引用捕获。
以=为例:
C++仿函数和Lambda表达式_第9张图片
     输出为:
在这里插入图片描述
     将“=”改为“&”,则输出为:
在这里插入图片描述
4,this捕获
     this捕获,在[]中传入this,表明以值传递的方式使用当前类中的成员变量。


5,混合捕获
     [=,&x] :变量x以引用形式捕获,其余变量以传值形式捕获。
     [&,x]:变量x以值的形式捕获,其余变量以引用形式捕获。
     以[=,&x] 为例:
C++仿函数和Lambda表达式_第10张图片
     输出为:
在这里插入图片描述

你可能感兴趣的:(C++)