c++11学习之——Lambda
写在前面的话:
C++11标准已经出来很多年了,但是自己一直都没有去认真学习过,还是用着以前的标准,感觉是时候认真学习下这些东西,就当成是给自己的大脑上点油,重拾一下学习的信心。
声明: 本文的内容出自阅读《深入理解C++11:C++新特性解析与应用》
Lambda的语法定义
[capture](parameters) mutable -> return-type(statement)
关于定义的解释:
- .[capture]:捕捉列表。
- 出现在lambda函数的开始处
- []是lambda函数的引出符,编译器根据该符号来判断接下来的代码是否是lambda函数
- 作用:用于捕捉上下文中的变量以供lambda函数使用
- .(parameters):参数列表
- 与普通函数的参数列表一样
- 如果不需要传递参数,可以省略括号()
- .mutable: mutable修饰符
- 默认情况下,lambda总是一个const函数
- 使用mutable修饰符时,即使参数列表是空,也不能省略括号()
- .->return-type: 返回值类型
- 不需要返回值时,连同箭头符号->可以一些省略
- 在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推导
- .{statement}:函数体
- 函数体的内容和普通函数一样
- 区别在于:除了参数列表中的参数,lambda函数还可以使用所有捕获的变量
目前存在的两点疑惑:
- const函数:目前就我的理解来说,const函数一般用于类的成员函数中,该函数的执行不会改变类对象的成员变量,不知道此处是否也是这个含义。
- 返回类型明确:什么情况被称为返回类型明确
捕捉列表
感觉上,捕捉列表是lambda函数和普通函数可见的最大区别之一,它决定了:
- 上下文中有哪些数据可以被lambda函数使用
- 以什么样的方式使用:
- 值传递的方式
- 引用传递的方式
语法上来说,捕捉列表由多个捕捉项组成,并且加以逗号分割,主要有几种形式:
- [var]:表示以值传递的方式捕捉变量var
- [&var]:表示以引用传递的方式捕捉变量var
- [=]:表示以值传递的方式捕捉所有父作用域的变量(包括this)
- [&]:表示以引用传递的方式捕捉所有父作用域的变量(包括this)
- [this]:表示值传递方式捕捉当前的this指针
一点疑惑:
- 什么是父作用域enclosing scope呢?
这里指的就是包含lambda函数的语句块,是否是一个{}内的语句块呢?又或者是包含了lambda函数的整个函数块内部。
通过一些组合,捕捉列表可以表示更加复杂的意思:
- [=, &a, &b] 表示以引用传递的方式捕捉变量a和b,值传递方式捕捉其他变量
- [&, a, b] 表示以值传递的方式捕捉变量a和b,引用传递的方式捕捉其他变量
需要注意的是:
- 捕捉列表不允许变量重复传递
- [=, a] =已经以传值方式捕捉了所有变量,捕捉a就重复了
- 不同作用域内的lambda函数
- 块级作用域{}外的lambda函数,捕捉列表必须为空
- 块级作用域{}内的lambda函数,仅能捕捉
父作用域中的自动变量
,不能捕捉非父作用域中或者非自动变量
一点疑惑:
- 什么是自动变量?
- 具有自动存储期:程序进入变量定义所在的块时该变量存在,退出块时销毁
- 块作用域和无连接:只有在变量定义所在的块才能通过变量名访问该变量
Lambda和仿函数
用了这么多年,我竟然还不了解什么是仿函数,仅仅知道的是:
- 仿函数是重新定义了操作符()的类对象
- 用起来就好像是真正的函数,但本质上却不是
在这里,需要注意的一个概念是【函数的初始状态】
仿函数
举个简单的栗子:
class _functor
{
public:
int operator()(int x, int y)
{