罗剑锋的 C++ 实战笔记
罗剑锋
前奇虎 360 技术专家,Nginx/OpenResty 开源项目贡献者
35514 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 32 讲
结束语 (1讲)
罗剑锋的 C++ 实战笔记
15
15
1.0x
00:00/00:00
登录|注册

10 | lambda:函数式编程带来了什么?

lambda表达式是否能代替类的成员函数
对函数式编程的理解和认识
lambda表达式的使用建议
lambda表达式的特点
泛型的lambda
lambda的变量捕获
lambda的形式
lambda表达式的灵活性
lambda表达式的变量捕获
lambda表达式与普通函数的区别
函数在C/C++里的特殊之处
函数概念来源于C
课下作业
小结
使用lambda的注意事项
认识lambda
C++函数的特殊性
lambda表达式

该思维导图由 AI 生成,仅供参考

你好,我是 Chrono。
第 1 节课的时候,我就说到过“函数式编程”,但只是简单提了提,没有展开讲。
作为现代 C++ 里的五种基本编程范式之一,“函数式编程”的作用和地位正在不断上升,而且在其他语言里也非常流行,很有必要再深入研究一下。
掌握了函数式编程,你就又多了一件“趁手的兵器”,可以更好地运用标准库里的容器和算法,写出更灵活、紧凑、优雅的代码。
所以,今天我就和你聊聊函数式编程,看看它给 C++ 带来了什么。

C++ 函数的特殊性

说到“函数式编程”,那肯定就要先从函数(function)说起。
C++ 里的函数概念来源于 C,是面向过程编程范式的基本部件。但严格来说,它其实应该叫“子过程”(sub-procedure)、“子例程”(sub-routine),是命令的集合、操作步骤的抽象。
函数的目的是封装执行的细节,简化程序的复杂度,但因为它有入口参数,有返回值,形式上和数学里的函数很像,所以就被称为“函数”。
在语法层面上,C/C++ 里的函数是比较特别的。虽然有函数类型,但不存在对应类型的变量,不能直接操作,只能用指针去间接操作(即函数指针),这让函数在类型体系里显得有点“格格不入”。
函数在用法上也有一些特殊之处。在 C/C++ 里,所有的函数都是全局的,没有生存周期的概念(static、名字空间的作用很弱,只是简单限制了应用范围,避免名字冲突)。而且函数也都是平级的,不能在函数里再定义函数,也就是不允许定义嵌套函数、函数套函数
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

C++中的lambda表达式为函数式编程带来了革命性的变化。传统的C++函数概念源自C,是面向过程编程的基本部件,但lambda表达式的引入使得函数成为了“一等公民”,可以像变量一样被赋值、限制作用域和生命周期,实现函数的局部化。此外,lambda表达式还具备“闭包”的特性,可以捕获外部变量,在内部代码中直接操作,使得函数式编程与命令式编程在结构上有了很大不同。函数式编程将程序视为由一个个函数组成,函数互相嵌套、组合、调用完成任务,与面向对象编程的实体对象通信完成任务的方式有所不同。lambda表达式的引入为C++带来了全新的编程思维方式,使得编程更加灵活、自由,能够更好地运用标准库里的容器和算法,写出更灵活、紧凑、优雅的代码。lambda表达式的形式简洁,可以在很多地方代替普通函数,甚至可以实现泛型化。然而,滥用lambda表达式可能会导致难以阅读的代码,需要在实践中慢慢积累经验,找到最适合自己的使用方式。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《罗剑锋的 C++ 实战笔记》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(48)

  • 最新
  • 精选
  • 罗剑锋
    置顶
    我在GitHub的lambd.cpp里写了一小段代码,示范了function + lambda实现成员函数的方法,算是对课下作业2的一个参考,同学们可以看看。
    2020-05-29
    2
    22
  • 冻冻
    老师,用“map+lambda”的方式来替换难以维护的 if/else/switch,能举个例子吗?

    作者回复: 这个需要用到std::function,存储lambda表达式,比如 ~~~ map<int, function<void()>> funcs; funcs[1] = [](){...}; funcs[7] = [](){...}; funcs[42] = [](){...}; return funcs[x](); ~~~ 这样,就把switch/case语句转换成了function+lambda,让map替你自动switch。

    2020-05-28
    6
    64
  • 被讨厌的勇气
    采用lambda表达式替换类的成员函数,成员变量通过 '[this]'可以捕获(相当于成员函数中的this参数),参数、返回值、函数体,lambda表达式都可以实现,所以理论上,是可以替换的。 试了一下,报错:在类内部无法定义auto。之前老师提到过的。

    作者回复: 对的,就是这个原因。

    2020-05-28
    2
    23
  • xGdl
    lambda由类的operator重载而来,最大的特征是携带私货(闭包),我一般使用闭包最多的就是将任务打包Task推送线程池或下一个流程。这一过程在没有闭包之前,实现起来有些麻烦。

    作者回复: 这个就是闭包最常用的场景之一了,把数据和逻辑打包传递。

    2020-06-04
    2
    17
  • 海怪哥哥
    关于lambda对于外部变量的捕获。大家可以这样理解更容易,如果把lambda表达式看成一个常规的变量,那么相同作用域(比如同一个函数)内的变量跟常量对它都是可见的。

    作者回复: 这个方法不错,nice。

    2020-06-12
    9
  • sp0917
    罗老师, auto pfunc = &my_square; 【1】 auto pfunc = my_square; 【2】 这两种表示有什么区别? 我一直认为函数名和函数指针是对等的,所以我直觉就是使用【2】,但发现这两个在使用pfunc进行操作时效果一样。

    作者回复: 是的,一般来说函数名就相当于函数指针,但对于成员函数,就必须要加上&。 所以我习惯上总写&,看起来更清楚,也比较一致。

    2020-07-28
    6
  • Charles
    感觉lambda和函数指针的差别好像不是太大,可能是我还没有真正理解吧,我觉得lambda的捕获功能,普通函数也可以用传引用的方式实现?然后将函数打包到别的地方,是不是也可以把普通函数的函数指针打包到别的地方?

    作者回复: lambda的一个最核心的特点是变量,是“一等公民”,可以嵌套定义,而函数不能做到,在函数里无法定义函数,所以只能用lambda来就地定义匿名函数。

    2020-07-24
    4
  • robonix
    老师,lambda表达式是不是没有常量引用呢?如果怕修改被捕获的变量只能用值传递,那么就有拷贝发生了?

    作者回复: 目前的lambda是这样的,不过你可以不在[]里捕获,而是在函数参数里传递常量引用。

    2020-06-09
    4
  • 张JL
    我常用lambda替换函数中的小段重复代码。 相同代码重复写几遍感觉很蠢,拿出来做成函数又没有必要,因为没有其他的调用需求,这时候用lambda就简洁多了

    作者回复: 对,用lambda来封装小段代码,这就有点函数式编程的意思了。

    2020-05-28
    4
  • Bluebuger
    Map + lambda是个好东西 想起了以前做 虚拟机时候指令操作码处理时候的一堆case(switch语句)

    作者回复: else/switch/case是我个人认为要极力避免的,它增加了代码的复杂度,分支太多导致逻辑不清。

    2020-06-25
    3
收起评论
显示
设置
留言
48
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部