前文回顾:
C++ 可调用对象总结(一) 函数对象
lambda
-
定义
一个 lambda 表达式表示一个可调用的代码单元,可以理解为是一个未命名的内敛函数。类似任何函数,一个 lambda 具有返回类型、参数列表和函数体;和普通函数不同, lambda 必须使用尾置返回来指定返回类型。
①.捕获列表
捕获列表是一个 lambda 所在函数中定义的局部变量的列表,捕获列表能够捕捉上下文中的变量以供 lambda 使用。
捕获列表可以为空,但 [] 不可以省略,编译器依次来判断接下来的代码是否是 lambda 表达式。
②.参数列表
和普通函数的参数列表一致,如果不需要参数传递,则可以连同括号 () 一起省略。lambda 中参数不能有缺省值,也不能有无名参数。
③.mutable
默认情况下,对于一个值被拷贝的变量,lambda 不会改变其值,加上 mutable 修饰符后,可以修改传递进来的拷贝。
在使用 mutable 修饰符时,参数列表部分不可省略,但列表可以为空。
④.返回类型
标识函数返回值的类型,当返回值为 void,或者函数体中只有一处 return 时可用省略。
⑤.函数体
标识函数的实现,内容与普通函数一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
函数体不能省略,但函数体可以为空。
-
捕获列表
①.概念
一个 lambda 通过将局部变量包含在其捕获列表中来指定将会使用这些变量,只能使用明确指明的变量;变量捕获方式可以传值捕获,也可以传引用捕获。
②.按值捕获变量
在捕获列表中指定变量名字,类似传值的参数,被捕获的变量值将在 lambda 创建时被拷贝。
③.按引用捕获变量
用 & 引用捕获,一个以引用方式捕获的变量,在 lambda 中被使用时,实际上使用的引用所绑定的对象。
④.多参数捕获
捕获列表中可以指定捕获多个参数,并且可以为每个参数指定捕获方式。
⑤.隐式按值捕获
使用 [=] 表示按值捕获 lambda 所在范围内所有可见的局部变量。
⑥.隐式按引用捕获
使用 [&] 表示按引用方式捕获 lambda 所在范围内所有可见的局部变量。
⑦.隐式混和捕获
使用 [=,prams] 表示除 xxx 按引用捕获外,其他所有参数按值捕获;使用 [&,prams] 表示除 xxx 按值捕获外,其他所有参数按引用捕获。
-
可变 lambda
默认情况下 lambda 不会改变按值捕获的变量,如果希望改变一个被拷贝的值,必须使用 mutable 关键字,且参数列表不能省略。
-
指定返回类型
如果一个 lambda 函数体包含了 return 之外的任何语句,则编译器假定返回类型为 void,此时我们必须指定返回值类型。
-
lambda是函数对象
定义一个 lambda ,编译器会生成一个与 lambda 对应的新的类类型。当向一个函数传递一个 lambda 时,同时定义了一个新类型和该类型的一个对象,生成的类包含所捕获变量对应的数据成员,数据成员在类创建时被初始化。
int sum = 0; std::vector<int> vec = { 1,2,3,4,5 }; std::for_each(begin(vec), end(vec), [&sum](int x){sum += x;});
上述代码被编译器翻译后变为:
class lambda_b { private: int* m_pSum; public: lambda_b(int* pSum) { m_pSum = pSum; } void operator()(int x) const { *m_pSum += x; } }; int sum = 0; std::vector<int> vec = { 1,2,3,4,5 }; std::for_each(begin(arry), end(arry), lambda_b(&sum));
-
lambda 使用
lambda 表达式实际为一个函数对象,可以把匿名函数保存在变量当有名函数来使用。
①.使用 auto 保存
int a = 1; int b = 2; //使用 auto 保存 lambda auto func = [a, &b](int c)mutable ->int { b = a + c; return a; }; //做有名函数使用 cout << b << " "<< func(10) << endl;
②.函数指针保存
当 lambda 的捕获外部变量列表为空时,可使用普通函数指针来保存。
//使用函数指针保存 lambda int(*func1)(int) = [](int x) {return x; }; //函数调用 int a = func1(20);
③.使用 std::function 模板类型
#include <functional> std::function<float(int,float)> fun1 = [](int x, float y) { return x + y; }; float a = fun1(12,1.2);//函数调用