概念
- 谓词
- 可调用的表达式
- lambda表达式
- 一个可调用的代码单元
- 一个未命名的内联函数
lambda表达式
-
形式
- [ capture list ] (parameter list) -> return type
-
捕获列表
- lambda所在函数中定义的局部变量列表
- 可直接使用局部static变量和lambda所在函数之外声明的名字
-
参数列表
- 可忽略
- 不能有默认参数
- 逗号分隔
- 可捕获在创建lambda表达式的作用域内可风的 非静态 局部变量
- 依赖于所捕获的这些局部变量
- 同时也依赖于lambda表达式形参
- 还可以直接使用静态存储期对象
- 也会依赖于这些对象
- 空捕获
- []
- 默认捕获(值捕获)
- [names]
- 显式捕获
- 值捕获
- [=, identifier_list]
- 捕获变量的值是在lambda创建时拷贝
- 对应着闭包类中的数据成员
- 引用捕获
- [&, identifier_list]
- 无须在闭包类中将其存储为数据成员
- 值捕获
- 隐式捕获
- 让编译器根据lambda体中的代码推断要使用哪些变量
- [&]
- 注意空悬引用
- [=]
- 不推荐使用
- [&]
- 让编译器根据lambda体中的代码推断要使用哪些变量
- 混合捕获
- [=, &os]、[=, identifier_list]、[&, identifier_list]等
- 捕获当前对象
- 显示捕获this
- 出现任一种捕获类型时:[&, ... ]、[=, ... ]、[&]、[=],当前对象都默认是以引用方式被捕获,并且访问成员变量时不需要以this->调用
- 伪初始化捕获
- c++11中使用std::bind实现
- 初始化捕获
- c++14
-
返回类型
- 可忽略
- 必须尾置返回
-
函数体
-
定义
- 当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名)类类型,闭包类
- 这个新类型的数据成员也是在lambda对象被创建时初始化
- 默认情况下,lambda生成的闭包类中的operator()成员函数会带有const饰词
- lambda表达式的声明中可以显式指定mutable:
- 当向一个函数传递一个lambda时,同时定义了一个新类型(闭包类)和该类型的一个对象(闭包):传递的参数就是此编译器生成的类类型的未命名对象
- 当使用auto定义一个用lambda初始化的变量时,定义了一个从lambda生成类型的对象
- 当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名)类类型,闭包类
其他相关语言特性
decltype
-
背景
- 从表达式的类型推断出要定义的变量的类型,但不想用该表达式的值初始化变量
-
概念
- 一种类型说明符
- 选择并返回操作数的数据类型
- c++11中主要用途大概就在于:声明那些 返回值型别 依赖于 形参型别 的 函数模板
-
decltype使用的表达式:
- 是一个变量
- 返回该变量的类型
- 不是一个变量
- 返回表达式结果对应的类型
- 如表达式的内容是解引用操作, 则decltype将得到(左值)引用类型
- 返回表达式结果对应的类型
- 一些特殊情况:比仅有名字更复杂的左值表达式(不仅是一个型别为T的名字)
- 得出的型别总是左值引用(对于型别为T的左值表达式,除非该表达式仅有一个名字,否则decltype总是得出型别T&)
- 如int x = 0;时decltype((x))的结果成了int&
- 得出的型别总是左值引用(对于型别为T的左值表达式,除非该表达式仅有一个名字,否则decltype总是得出型别T&)
- 是一个变量
尾置返回类型
- 本应该出现返回类型的地方放置一个auto,形如:
- auto func( int i ) -> int(*)[10]
泛型lambda表达式
- 在形参规格中使用auto
- c++14
lambda表达式可变长形参
- c++14
参考
Lambda expressions (since C++11)
《C++ Primer(第五版)》
《Effective Modern C++》