博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++ lambda表达式
阅读量:5092 次
发布时间:2019-06-13

本文共 2141 字,大约阅读时间需要 7 分钟。

一、lambda表达式

(1) lambda表达式的一般形式: [ capture list ] ( parameter list ) -> return type { function body }

     其中参数列表和返回类型可以省略,但必须永远包含捕获列表和函数体 。比如:

auto f = [] { return 42; }

 

    注意:在忽略返回类型的情况下,如果函数体只有一条return语句,则返回类型从返回的表达式的类型推断出来;

             如果一个函数体包含任何除return意外的语句,编译器都将返回类型推断为void。

(2) 一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数体中使用该变量。

1 //错误: sz未捕获2     int sz = 2;3     auto f = [] (const string &a) { return a.size() >= sz; };

 

   注意:捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和它所在函数之外声明的名字(全局变量)。

1 int main() 2 { 3     //正确,sz为static变量 4     static int sz = 2; 5     auto f = [] (const string &a) { return a.size() >= sz; }; 6     return 0; 7 } 8 int sz = 2; 9 int main()10 {11     //正确,sz为全局变量12     auto f = [] (const string &a) { return a.size() >= sz; };13     return 0;14 }

 

 

(3) 被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝。

1 int main()2 {3     int a = 42;4     auto f = [a] { return a; };5     a = 0;6     cout << f() << ',' << a;   //f保存的时我们创建它时a的拷贝7     return 0;                   //所以此处的输出为42,08 }

 

(4) 隐式捕获

1 int main()2 {3     int a = 42;                  //=表示采用值捕获的方式进行隐式捕获,&表示采用引用捕获的方式进行隐式捕获4     auto f = [=] { return a; };  //隐式捕获a5     a = 0;6     cout << f() << ',' << a;   7     return 0;                 8 }

 

 

(5) 可变lambda:当我们要改变捕获变量的值的时候,必须在参数列表后加上关键字mutable,参数列表里面的参数可以省略,但是括号不能省略

1 int main() 2 { 3     int a = 42; 4     auto f = [a] () mutable { return ++a; }; //此时参数列表()不能省略! 5     cout << f() << ',' << a;   //输出为43,42 6      7      8     auto g = [&a] () mutable { return ++a; }; 9     cout << g() << ',' << a;   //输出还是43,42 ;a的值(引用)并未修改,因为cout的嵌套使用出现了问题10     11     cout << g() << endl; 12     cout << a;                 //此时输出为43,43。因为此时cout的调用未出错13     return 0;14 }

 

 

cout << g( ) << ',' << a ;     结果出错的原因:

这和lambda表达式无关,而和cout的嵌套调用有关。cout的嵌套出了问题,使得结果未定义

cout<<g()<<a相当于operator<<的嵌套调用:operator<<(operator<<(cout, g()), a),而g()中又对a的值做了有副作用的修改,因此,这是一个未定义行为,因为C++中没有规定函数参数的求值顺序,结果取决于编译器实现。如果编译器从右向左求值,那么两个参数将分别求值得到43, 42,这是VC++和gcc的实现方式;如果编译器从左向右求值,那么两个参数将分别求值得到43, 43。两种结果都符合C++规范。这和lambda表达式无关,而和cout的嵌套调用有关。

 

总结:当其中一个输出的变量a会对另一个输出的变量b的值产生影响的时候,不应在同一条cout语句中同时输出a和b,而应该将它们分别在两条cout语句中输出,这样可以避免出错。

 

转载于:https://www.cnblogs.com/FengZeng666/p/9272058.html

你可能感兴趣的文章
matlab 给某一列乘上一个系数
查看>>
密码学笔记——培根密码
查看>>
Screening technology proved cost effective deal
查看>>
MAC 上升级python为最新版本
查看>>
创业老板不能犯的十种错误
查看>>
Animations介绍及实例
查看>>
判断请求是否为ajax请求
查看>>
【POJ2699】The Maximum Number of Strong Kings(网络流)
查看>>
spring boot配置跨域
查看>>
BZOJ 1996 合唱队(DP)
查看>>
进击吧!阶乘——大数乘法
查看>>
安卓学习资料推荐-25
查看>>
Mysql数据库备份和还原常用的命令
查看>>
关于退出当前页面在火狐的一些问题
查看>>
【项目实施】项目考核标准
查看>>
spring-aop AnnotationAwareAspectJAutoProxyCreator类
查看>>
经典入门_排序
查看>>
Redis Cluster高可用集群在线迁移操作记录【转】
查看>>
二、spring中装配bean
查看>>
VIM工具
查看>>