C++ lambda 用法
1. 为什么要使用lambda
+ 就地匿名的定义一个目标函数或者函数对象,不需要额外的再写一个命名函数或者函数对象,以更直接的方式去写函数,可以调高程序的可读性和可维护性。
+ 简洁:不要额外的的再写一个函数或者函数对象,避免了代码膨胀或者功能分散。
+ 在需要的时间或者地点实现功能闭包,是程序更加灵活。
2. lambda 的语法
+ [capture] (parameters) mutable->return-type{statement};
3. lambda 的内部实现
+ 编译器会自动生成一个匿名类,该类重载了 () 运算符。
int id = 0; auto f = [id]() mutable { cout << "id: " << id << endl; ++id; };
+ 当写出上面一块代码时,那么编译器就会将他们转换成以下的代码
class Functor { private: int id; public: void operator() (){ std::cout << "id: " << id << endl; ++id; } };
+ 其中,函数名具体是取决于编译器自己编译,私有成员变量是捕获列表所来,重载的 () 操作符函数具体是由 lambda 表达式 body 所来
4. lambda 的使用
1. 捕获列表:
+ []:什么也不捕获
+ [=]: 按值的方式捕获所有变量
+ [&]: 按引用方式捕获所有变量
+ [boo]:值捕获 boo 的值
+ [=, &a]: 按值捕获所有局部变量,按引用捕获变量a。
+ [=, &a, &b, &c]:同上,
+ [&, a]:按引用捕获所有局部变量,按值捕获方式捕获 a
+ [&, a, b, c]:同上
+ [this]:在成员函数中,直接捕获 this 指针
2. mutable:
+ 值捕获后,在匿名函数中对该值是不能做修改的,如果想要做修改,必须加上 mutable 关键字,并且在匿名函数中做的修改结果在函数外是不会生效的;
3. parameters:
+ 参数列表也是可以将外部的值传递给匿名函数内部的,和捕获列表的在于,parameter 对应的 operator函数的形参列表。
4. return-tyep:
+ 对于编译器能自动推导的返回类型,可以省略 return-type,但是如果无法推导的类型,就必须添加上返回类型
+ 当函数不止一个return语句时,就需要加上返回类型了。
+ 总结:
1. 捕获列表中,捕捉的值会作为类的私有成员生成,且是const类型,所以值捕获的数值无法在匿名函数中修改,引用捕获可以修改,且这种改变可以传到外部。
Example:
#include<iostream> using namespace std; void capturePassedByValueAll(); void capturePassedByReferenceAll(); void capturePassedByValueExceptSome(); void lambdaMutable(); void lambdaParameter(); void lambdaReturnType(); int main() { // passed by value capturePassedByValueAll(); // passed by reference capturePassedByReferenceAll(); // passed by value all excpet some capturePassedByValueExceptSome(); // passed by value all and mutable lambdaMutable(); // lambda in parameter lambdaParameter(); // lambda in return lambdaReturnType(); return 0; } void lambdaReturnType() { auto autoGetRetutnType = []() { return 5+3; }; cout << "lambdaReturnType = " << autoGetRetutnType() << endl; auto specifyReturnType = [](int x)->string { if (x > 0) { return "x more than zero"; } else { return "x less than zero"; } }; cout << "specifyReturnType = " << specifyReturnType(2) << endl; } void lambdaParameter() { int a = 1; int b = 2; auto f = [](int a, int b) { return a > b ? a : b; }; cout << "lambdaParameter f(a,b) = " << f(a, b) << endl; } void lambdaMutable() { int a = 1; int b = 2; auto passedByValueMutable = [=]()mutable { cout << "lambdaMutable start a :" << a << " b: " << b << endl; a++; b++; cout << "modify after a :" << a << " b: " << b << endl; }; passedByValueMutable(); cout << "lambdaMutable a :" << a << " b: " << b << endl; } void capturePassedByValueExceptSome() { int a = 0; int b = 1; int c = 100; int d = 200; auto passedByValueExceptSome = [=, &c, &d]() { cout << "capturePassedByValueExceptSome start a = " << a << " b = " << b << endl; cout << "midify after c = " << c << " d = " << d << endl; c++; d++; cout << "midify after c = " << c << " d = " << d << endl; cout << "capturePassedByValueExceptSome end" << endl; }; passedByValueExceptSome(); cout << "a = " << a << " b = " << b << endl; } void capturePassedByReferenceAll() { int c = 100; int d = 200; auto passedByReference = [&] { cout << "passedByReference c = " << c << " d = " << d << endl; c++; d++; cout << "c = " << c << " d = " << d << endl; cout << "passedByReference end" << endl; }; passedByReference(); cout << "c = " << c << " d = " << d << endl; } void capturePassedByValueAll() { int a = 0; int b = 1; auto passedByValue = [=]() { cout << "passedByValue start a = " << a << " b = " << b << endl; cout << "passedByValue end" << endl; }; passedByValue(); cout << "a = " << a << " b = " << b << endl; }