上一篇C++的博客是Long Long ago了,前文讲到在看Lambda表达式的内容。笔者首次接触Lambda表达式应该是学习Python语言的时候,当时也不太明白这种表达方式的精髓,后续接触了Scala与Java8的链式调用与Lambda结合的方式,深陷无法自拔。所以借上一篇闭包的内容。我们来完整的梳理一下C++之中的Lambda表达式。

1.什么是Lambda表达式?

Lambda表达式是函数式编程的重要的语法结构。

Lambda 表达式(lambda expression)说起来很简单,就是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包。(注意和数学传统意义上的不同)。(本质上Lambda表达式就是将函数作为是一个匿名对象进行操作

其实缺少Lambda表达式的编程语言并不会影响编程语言的逻辑表达,Lambda表达式核心就是提供一个好用的语法糖:可以直接定义一个函数,而不需要将定义函数和语法内容分开,这样有助于将逻辑用更紧凑的方式表达出来。假如需要定义一个函数,恰巧这个函数仅仅使用一次,然后又需要给它定义一个名字,作为懒惰的程序员就需要搬出Lambda表达式了。咱们看一段Python代码,过滤一个list之中的偶数,这是一个很简单的需求,我们先看看不使用Lambda表达式的方式:

def isOdd(n):
return n & 1; nums = [1,2,3,4,5,6]
nums = filter(isOdd,nums)

显然这里需要额外定义一个代码逻辑十分麻烦:首先需要跳脱出运行代码而去查看定义的isOdd函数的代码,其次,这里需要实现的过滤逻辑很简单。这种场合是最适合使用Lambda表达式的场景,我们来看看Lambda表达式是怎么优化上述代码的:

nums = [1,2,3,4,5,6]
nums = filter(lambda x:x & 1,nums)

好吧,很优雅的用Lambda表达式解决了同样的需求,表述也十分清晰:

下面的几个使用场景是适用于Lambda表达式的:

  • (1)代码定义的逻辑与执行逻辑对接的更加紧凑。
  • (2)代码更加简洁。
  • (3)能够支持闭包。

2.C++之中的Lambda表达式

C++在C++11之中添加了Lambda表达式的语法结构,Lambda语法结构如下所示:

[capture](parameters)->return-type {body}

接下来,我们来一一分析各个部分所代表的含义,以及具体的使用方式:

  • [capture]

    capture代表捕获外部的变量,这个使用的方式笔者在上一篇有关闭包的内容之中就有过示例,变量捕获是Lambda表达式之中,最为复杂的一环,我们来看一看其中各种表示方式的含义:

    • [] 不捕获任何变量(但是必须得写,编译器通过捕获结构识别Lambda表达式
    • [&} 通过引用的方式捕获外部作用域中所有变量
    • [=] 通过拷贝的方式捕获外部作用域中所有变量

      上述两种方式都过于粗暴了,实际的话,尽量采用下面的模式来限定所引用的变量,不要随意引用
    • [x, &y] x按值传递,y按引用传递
    • [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。

可以看到,[capture]的语法结构捕获了外部变量,通过这样的方式实现了闭包

  • (parameters)

    这个部分很简单,类似于通常函数使用的参数列表,使用方式也没有区别。

  • ->return-type

    显式指明由Lambda表达式所返回的返回值类型。这里通常建议不写,因为C++编译器会通过类型推断的方式来推断出函数的返回值类型,而且前面的->也可以省略。

  • {body}

    花括号括起来的函数体,则没什么好说的了,就是实现函数逻辑的部分了。

同样的,我们来看看上文用python实现的过滤偶数的代码在C++之中是如何实现的:

    vector<int> nums = {1,2,3,4,5,6,7};
vector<int> newNums(nums.size()); auto last = copy_if(nums.cbegin(), nums.cend(),newNums.begin(),[](int x){return !(x & 1);});
for_each(newNums.begin(), last, [](int x) {
cout << x << endl;
});

和python的实现相比,由于缺少了链式调用的方式,所以看起来C++实现的版本并没有简化多少应用逻辑,反而看起来略显杂乱。但是这并不妨碍我们在适当的地方运用Lambda表达式,来优化我们的代码结构。

3.其他语言与Lambda表达式

  • Java

    Java在Java 8的版本终于千呼万唤始出来的Lambda表达式确实是让个人很喜欢,个人也觉得Java 8对于Java这门语言有极其深远的影响。我们来看看Java之中是如何实现上文的逻辑的:
public static void main(String[] args) {
int[] nums = {1,2,3,4,5,6,7};
IntStream.of(nums).filter((x)->{return (x & 1) == 1;}).forEach(System.out::println);
}

相比C++而言优雅了很多,而且参数类型也能做到类型推断,对程序员来说确实更加友好了。

坦白说:Java是一门很幸运的语言,更上了移动开发,大数据的浪潮。不过随着Google与Oracle的官司,不知道Java未来是否还能继续现在的强势地位。

  • Golang

    没有Lambda表达式,咱们要的是简洁明晰,不要学Geek那一套玩意。

4.小结

感觉本文干货有点略少,吐槽略多,见谅哈~~~。关于C++之中的Lambda表达式就和大家聊到这里,希望大家在实际Coding之中可以用好它,来尽量简洁化自己的代码结构。

C++雾中风景8:Lambda表达式的更多相关文章

  1. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  2. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  3. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

  4. Kotlin的Lambda表达式以及它们怎样简化Android开发(KAD 07)

    作者:Antonio Leiva 时间:Jan 5, 2017 原文链接:https://antonioleiva.com/lambdas-kotlin/ 由于Lambda表达式允许更简单的方式建模式 ...

  5. java8中lambda表达式的应用,以及一些泛型相关

    语法部分就不写了,我们直接抛出一个实际问题,看看java8的这些新特性究竟能给我们带来哪些便利 顺带用到一些泛型编程,一切都是为了简化代码 场景: 一个数据类,用于记录职工信息 public clas ...

  6. 背后的故事之 - 快乐的Lambda表达式(二)

    快乐的Lambda表达式 上一篇 背后的故事之 - 快乐的Lambda表达式(一)我们由浅入深的分析了一下Lambda表达式.知道了它和委托以及普通方法的区别,并且通过测试对比他们之间的性能,然后我们 ...

  7. CRL快速开发框架系列教程二(基于Lambda表达式查询)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  8. Lambda 表达式递归用法实例

    注意: 使用Lambda表达式会增加额外开销,但却有时候又蛮方便的. Windows下查找子孙窗口实例: HWND FindDescendantWindows(HWND hWndParent, LPC ...

  9. Spark中Lambda表达式的变量作用域

    通常,我们希望能够在lambda表达式的闭合方法或类中访问其他的变量,例如: package java8test; public class T1 { public static void main( ...

随机推荐

  1. 关于ZK框架的onScroll事件的问题

    由于我现在所在的公司用到的zk框架,遇到了一个需求frozen on top. 简单来说就是滚动超过范围后,希望有一块东西停留在滚动窗口的顶部. 一.zk框架 查看了zk的8.x版本,发现组件的支持的 ...

  2. python—-模块与包1

    模块与包 1 什么是模块? 一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀 2 为何要使用模块? 如果你对出python解释器然后重新进入,那么你之前定义的函数 ...

  3. c#:实现动态编译,并实现动态MultiProcess功能(来自python multiprocess的想法)

    由于之前一直遇到一些关于并行进行数据处理的时效果往往不好,不管是c#还是java程序都是一样,但是在Python中通过multiprocess实现同样的功能时,却发现确实可以提高程序运行的性能,及服务 ...

  4. hermite矩阵

    在读线代书.因为之前并没有上过线性代数的课.所以决定把基础打牢牢. 读书的时候当然会出现不懂的概念和术语或者定理什么的.所以在这记录一下啦--- hermit矩阵要理解它好像先要知道什么是共轭(con ...

  5. [LeetCode] Non-negative Integers without Consecutive Ones 非负整数不包括连续的1

    Given a positive integer n, find the number of non-negative integers less than or equal to n, whose ...

  6. pandas用法大全

    pandas用法大全 一.生成数据表 1.首先导入pandas库,一般都会用到numpy库,所以我们先导入备用: import numpy as np import pandas as pd12 2. ...

  7. [POJ 3487]The Stable Marriage Problem

    Description The stable marriage problem consists of matching members of two different sets according ...

  8. [HNOI2010]PLANAR

    题目描述 若能将无向图G=(V,E)画在平面上使得任意两条无重合顶点的边不相交,则称G是平面图.判定一个图是否为平面图的问题是图论中的一个重要问题.现在假设你要判定的是一类特殊的图,图中存在一个包含所 ...

  9. HNOI2018 滚粗记

    day0 说好了不复习,于是复习了一下配置,没想到一下就记住了,咋不退役去搞英语竞赛捏 皇室一波攒RP,chicken chicken一波攒RP day1 机子坏了,换到了最后面,但这个时候已经 \( ...

  10. bzoj 4545: DQS的trie

    Description DQS的自家阳台上种着一棵颗粒饱满.颜色纯正的trie. DQS的trie非常的奇特,它初始有n0个节点,n0-1条边,每条边上有一个字符.并且,它拥有极强的生长力:某个i时刻 ...