lambda 表达式
基本用法
lambda 表达式是 C++11 最常用的特性之一,这是现代编程语言的一个特点,lambda 表达式的优点:
(1)声明式的编程风格:匿名定义目标函数或函数对象,不需要额外写一个命名函数或函数对象。
(2)简洁:避免了代码膨胀和功能分散,让开发更加高效。
(3)在需要的时间和地点实现功能闭包,使程序更加灵活。
lambda 表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。
lambda 表达式的语法形式如下:
1 |
|
其中 capture
是捕获列表,params
是参数列表,opt
是函数选项,ret
是返回值类型,body
是函数体。
捕获列表
lambda 表达式的捕获列表可以捕获一定范围内的变量,使用方式如下:[]
:不捕捉任何变量[&]
:捕获外部作用域中所有变量,并作为引用在函数体内使用(按引用捕获)[=]
:捕获外部作用域中所有变量,并作为副本在函数体内使用(按值捕获),拷贝的副本在匿名函数体内部是只读的[=, &foo]
:按值捕获外部作用域中所有变量,并按照引用捕获外部变量 foo[bar]
:按值捕获 bar 变量,同时不捕获其他变量[&bar]
:按引用捕获 bar 变量,同时不捕获其他变量[this]
:捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数相同的访问权限。如果已经使用了 & 或者 = 默认添加此选项。
使用初始化列表的用法,示例代码:
1 |
|
在匿名函数内部,需要通过 lambda 表达式的捕获列表控制如何捕获外部变量,以及访问哪些变量。默认状态下 lambda 表达式无法修改通过复制方式捕获外部变量,如果希望修改这些外部变量,需要通过引用的方式进行捕获。
返回值
很多时候 lambda 表达式的返回值是非常明显的,因此在 C++11 中允许省略 lambda 表达式的返回值。
一般情况下,不指定 lambda 表达式的返回值,编译器会根据 return 语句自动推导返回值的类型。
1 |
|
需要注意的是 lambda 表达式不能通过列表初始化自动推导出返回值类型。
1 |
|
函数
使用 lambda 表达式捕获列表捕获外部变量,如果希望修改按值捕获的外部变量,那么应该如何处理呢?
使用 mutable
选项,被 mutable
修饰的 lambda 表达式没有参数也要写明参数列表,并且去掉按值捕获的外部变量的只读 const
属性。
1 |
|
为什么通过值拷贝的方式捕获的外部变量是只读的?
(1)lambda 表达式的类型在 C++11 中被看做是一个带 operator()
的类(仿函数)。
(2)按照 C++ 标准,lambda 表达式的 operator()
默认是 const
的,一个 const
成员函数是无法修改成员变量值的。mutable
选项的作用就在于取消 operator()
的 const
属性。
lambda
表达式在 C++ 中被看做是一个仿函数,因此可以使用 std::function
和 std::bind
存储和操作 lambda 表达式:
1 |
|
对于没有捕获任何变量的 lambda
表达式,可以转换成一个普通的函数指针:
1 |
|