最近在接手一个模块,看到了很多奇葩的语法,查了一下是lambda表达式,这块还真不了解。周末学习一下记录记录。
lambda表达式是C++11最重要也最常用的一个特性之一。lambda来源于函数式编程的概念,也是现代编程语言的一个特点。目前支持lamdba的语言不少,如python,C++11, Java等。
lambda表达式的语法归纳如下:
[ caputrue ] ( params ) opt -> ret { body; };
1).capture是捕获列表;
2).params是参数表;(选填)
3).opt是函数选项;可以填mutable,exception,attribute(选填)
mutable说明lambda表达式体内的代码可以修改被捕获的变量,并且可以访问被捕获的对象的non-const方法。
exception说明lambda表达式是否抛出异常以及何种异常。
attribute用来声明属性。
4).ret是返回值类型。(选填)
5).body是函数体。
捕获列表说明:lambda表达式的捕获列表精细控制了lambda表达式能够访问的外部变量,以及如何访问这些变量。
1).[]不捕获任何变量。
2).[&]捕获外部作用域中所有变量,并作为引用在函数体中使用(按引用捕获)。
3).[=]捕获外部作用域中所有变量,并作为副本在函数体中使用(按值捕获)。
4).[=,&foo]按值捕获外部作用域中所有变量,并按引用捕获foo变量。
5).[bar]按值捕获bar变量,同时不捕获其他变量。
6).[this]捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限。如果已经使用了&或者=,就默认添加此选项。捕获this的目的是可以在lamda中使用当前类的成员函数和成员变量。
注意点:
(1) 如果是使用按值捕获,则在定义时已经将值复制;
如果是使用按引用捕获,则在实际使用时才进行取值。
(2) printf函数/std::cout 的计算顺序:先从右到左压栈,然后从左到右出栈。
测试例子:
1 #include <iostream> 2 3 int main() 4 { 5 int x = 1, y = 1; 6 7 //不带参数, 不捕获变量 8 auto f1 = []{std::cout<<"hello"<<std::endl;}; 9 f1(); //输出:hello 10 11 //不带参数, 值传递方式捕获外部变量 12 auto f2 = [=]() {return x + 1;}; 13 std::cout << x << " " << f2() << std::endl; //输出:1 2 14 15 //带一个参数 16 //值传递捕获y, 引用传递x 17 auto f3 = [&x,y](int a) mutable {x = x + a + y; ++y; return x;}; 18 std::cout << "x = " << x 19 << ", y = " << y 20 << ", f3(5) = " << f3(5) << std::endl; 21 22 //综合例子 23 int a = 1, b = 1, c = 1; 24 auto m1 = [a, &b, &c]() mutable { 25 auto m2 = [a, b, &c]() mutable { 26 std::cout << "m2():"<< "a = " << a 27 << ", b = " << b 28 << ", c = " << c << '/n'; 29 a = 4; b = 4; c = 4; 30 }; 31 a = 3; b = 3; c = 3; 32 m2(); 33 }; 34 35 a = 2; b = 2; c = 2; 36 37 m1(); // 调用 m2() 并打印 123 38 std::cout << "main():"<< "a = " << a 39 << ", b = " << b 40 << ", c = " << c << '/n'; 41 42 return 0; 43 }
编译执行:
g++ -std=c++11 test.cpp hello 1 2 x = 7, y = 1, f3(5) = 7 m2():a = 1, b = 2, c = 3 main():a = 2, b = 3, c = 4
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/17505.html