必须使用列别名命名此表达式_lambda表达式

44999325f22edd603b7a05b94a869258.png

一般的,如果一个类定义了函数调用运算符,则我们可以像使用函数一样使用这个类,例如:一个类A定义了函数调用运算符,我们就可以使用A()这样的形式调用对象,实际上调用了类的调用运算符函数。如果一个类定义了调用运算符,则该类的对象可以被称为函数对象(可调用对象包含:函数,函数指针,重载了函数调用运算符的类和lambda表达式)。在lambda表达式中,编译器将改表达式翻译为一个未命名的类未命名对象。lambda表达式产生的类中含有一个重载的函数调用运算符。默认情况下,lambda不能改变它捕获的变量(可以通过mutable关键字进行修改,后面会介绍)。因此,由lambda表达式产生的类中含有一个函数调用运算符的const成员函数(const成员函数有常量对象调用,一般不改变类的成员变量,例如get一个成员变量,应该在函数的参数列表后加上const关键字)。lambda表达式产生的类中不包含默认构造函数,赋值运算符和默认析构函数。是否含有默认的拷贝/移动构造函数则通常要视捕获的对象的类型而定。

lambda表达式来自于lambda演算,其定义如下:

λ演算_百度百科​baike.baidu.com
a3b81c9463aedd1bab86c9e5b803adcc.png

这里主要介绍下c++中的lambda表达式。

lambda表达式又被称为匿名函数,当我们在程序的某一处使用一个简单的函数,并且只在此处或者此作用域中使用一次或者几次,这时可以考虑使用lambda表达式。其基本语法如下:

ec6e28935a6a29e2b0bfb10af82596ac.png

lambda表达式的返回类型必须是尾置的。其中,参数列表返回类型(返回类型忽略时,lambda可以根据其函数体中返回类型进行推断)可以忽略。lambda表达式不能有默认参数,因此形参和实参的数量必须一致且一 一对应。lambda表达式内部是无法使用其所在函数中的(非static)变量的,但有时必须使用,就必须使用捕获列表来捕获其所在作用域中的参数(注意:只能捕获lambda所在作用域中的参数,函数外的变量可以直接使用。例如:我们在lambda表达式函数体中使用的cout,可以直接使用)。根据捕获参数的方式,可以分为:值捕获,引用捕获,隐式捕获表达式捕获。

捕获列表的形式如下:

3ed8ab450950ad6dbb6daf783de6a4e5.png

1 值捕获

通过值捕获的变量会被拷贝到lambda产生的类对象中,因此这种捕获方式必须为每个值捕获的变量建立对应的数据成员。同时创建构造函数,令其捕获的变量初始化数据成员。值捕获的对象必须是可拷贝的。但其捕获的值是在lambda表达式对象创建时拷贝,而不是运行时拷贝:

 //按值捕获int t=10;auto ff=[t]() mutable {   //注意:这里是lambda函数的声明return ++t;  //这里生成了一个_t的变量};auto ff2=[t]() mutable {   //注意:这里是lambda函数的声明return ++t;    //这里生成了一个_t的变量};cout<<ff()<<endl;   //这里调用lambda表达式cout<<ff2()<<endl;cout<<ff()<<endl;cout<<ff2()<<endl;cout<<t<<endl;/*运行结果
11
11
12
12
10
*/

上述ff和ff2其本质是编译器生成的未命名类的未命名对象。由于是值捕获,因此++t只在lambda函数作用域有效,捕获t后实际在内部生成了一个_t的成员变量lambda表达式内部对t的操作实际上是对_t这个变量的操作,并不影响其外部的t的值。

默认我们捕获到lambda表达式中的值是const的,是不能修改的,mutable关键字可允许我们对捕获到的值进行修改。因此,在上述代码中,++t的时候必须加上mutable。

上述lambda表达式等价于:

class cfun{
public:fun(t):_t(t){};bool operator(){  //由于这里使用了mutable关键字,因此是这样的_t++;}/*当没有mutable关键字时,函数调用运算符重载如下形式:bool operator()  const{/* 对_t的一些操作 */}*/private:int _t;
};

可变lambda

这里 再简单介绍下mutable的使用。默认情况下,lambda不会改变一个值被拷贝的变量。如果希望改变被捕获的变量,就必须使用mutable。因此,可变lambda可以省略参数列表。

void fun(){size_t v1=42;auto f=[v1] () mutable { return ++v1; };v1=0;auto j=f();  //j=43 
}

一个引用捕获的变量是否可以修改依赖于引用指向一个const对象还是非const对象。

void fun(){size_t v1=42;  //局部变量//v1是一个非const的变量引用,可以使用f来改变其值。auto f=[&v1] { return ++v1; };v1=0;auto j=f();  //j=1
}

2 引用捕获

当lambda用引用捕获变量时,由程序负责确保lambda执行时引用所引的对象确实存在。因此,编译器可以直接使用该引用而无需在lambda产生的类中将其存储为数据成员。

 //引用捕获
int t=10;
auto ff=[&t]() {cout<<t<<endl;t=13;
};
t=11;
ff();
cout<<t<<endl;//输出结果
/*
11
13
*/

可以看到,引用捕获的方式跟一般的引用形参函数类似,可以改变传入的参数值。

引用捕获是必要的,例如:

for_each(words.begin(),words.end(), [&os, c] (const string & s) { os<<s<<c; });

因为ostream对象os是不能拷贝的。

当然,我们也可以从一个函数中返回一个lambda,但是lambda在返回后,函数中的变量会被销毁,因此,lambda的捕获列表中不能包含函数中变量的引用。

3 隐式捕获

以上两种方式都是显式捕获方式,这里介绍下隐式捕获。编译器可以根据lambda函数体中的代码推断我们会使用那些变量。其中&告诉编译器引用捕获方式,=采用值捕获方式。

int a=1,b=2;
[a,b](){cout<<a<<"+"<<b<<endl;
}();//引用捕获
[&](){cout<<a<<"+"<<b<<endl;
}();//值捕获
[=](){cout<<a<<"+"<<b<<endl;
}();//混合使用
int c=3,d=4;
[=,&c,&d](){cout<<a<<"+"<<b<<endl;cout<<c++<<"+"<<++d<<endl;
}();

当我们使用混合方式时,捕获列表的第一个元素必须是&或者=。此符号指定了默认捕获方式。显式捕获必须使用与隐式捕获不同的方式。即,当默认捕获方式是值捕获时,显式捕获方式命名变量必须采用引用捕获方式。

4 指定lambda返回类型

如果lambda函数体中包含了除return的任何语句,编译器默认此lambda返回void。例如:

void fun(){auto ff4=[](int i){if(i<0)return -i;elsereturn i;};cout<<ff4(-100)<<endl;
}

此时会出现编译错误,正确的写法如下:

void fun(){auto ff4=[](int i)->int{if(i<0)return -i;elsereturn i;};cout<<ff4(-100)<<endl;
}

以下是一个lambda的使用例子:

void fun(){vector<int> vec={1,2,3,4,5};for(int i=0;i<vec.size();i++){if(vec[i]%2==0)cout<<vec[i]<<"是偶数"<<endl;elsecout<<vec[i]<<"是奇数"<<endl;}//高阶写法for_each(vec.begin(),vec.end(),[](int n){if(n%2==0)cout<<n<<"是偶数"<<endl;elsecout<<n<<"是奇数"<<endl;});
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245888.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql数据库出现幻读,MySQL 幻读怎样处理?_数据库

MySQL 幻读怎样处理&#xff1f;1、MVCC快照&#xff0c;将历史数据存一份快照&#xff0c;在其事件增添与删除数据时&#xff0c;保证当前事件来说是不可见的&#xff1b;多半数据库都完成了多版本并发掌握&#xff0c;而且都是靠保留数据快照来完成的。以 InnoDB 为例&#x…

搜索引擎提交软件_增加SEO超级外链须知的高权重网站目录提交方法

做SEO的朋友对开放式网站目录应该不陌生吧。网站目录就是按一定的分类方法把收录的网站进行分类归档。网站目录本身是不主动抓取网页的&#xff0c;一般只记录网站的名称&#xff0c;网址和有限的说明文字。和网址站、导航站、酷站网址大全等如同一辙。一般高质量的聚合目录网站…

matlab代码cwfac,主成分分析的matlab实现完整程序

主成分分析1.概述Matlab 语言是当今国际上科学界 (尤其是自动控制领域) 最具影响力、也是最有活力的软件。它起源于矩阵运算&#xff0c;并已经发展成一种高度集成的计算机语言。它提供了强大的科学运算、灵活的程序设计流程、高质量的图形可视化与界面设计、与其他程序和语言的…

把模糊MATLAB波形的图变清晰,什么修图软件能把模糊图片清晰化?

图片和内容的契合度再高&#xff0c;配色再完美&#xff0c;如果图片不清晰&#xff0c;那才真的是一图毁所有。针对这种情况&#xff0c;我也为大家找来两个非常实用的工具。第一个工具&#xff0c;SmartDeblur。主要针对原图分辨率不高的情况。这个软件目前支持三种模式&…

python写mapreduce_用python写MapReduce函数——以WordCount为例

使用python写MapReduce的“诀窍”是利用Hadoop流的API&#xff0c;通过STDIN(标准输入)、STDOUT(标准输出)在Map函数和Reduce函数之间传递数据。我们唯一需要做的是利用Python的sys.stdin读取输入数据&#xff0c;并把我们的输出传送给sys.stdout。Hadoop流将会帮助我们处理别的…

遗传算法在交通路线matlab,Matlab遗传算法公交车路线优化

Matlab遗传算法公交车路线优化Matlab遗传算法公交车路线优化Matlab遗传算法公交车路线优化1 模型介绍2模型分析2.1整体设计2.2要点分析3结果展示1 模型介绍以乘客出行总时间最小为目标函数&#xff0c;求出其最小值即为最终接驳优化方案。模型约束条件在算法过程中可能会产生不…

mysql 连续签到天数_新版签到活动明天上线,福利活动抢鲜看~

明天游戏中心app旧版福利签到活动马上就要结束啦&#xff0c;虽然很多的魅友反馈说积分签到结束的太早&#xff0c;积分不够换5折券&#xff0c;不过更早的开启新版签到才能更快的享受到更好的福利嘛~今晚0点新版签到活动即将上线&#xff0c;接下来就一起来看看新版的签到活动…

java中nio怎么实现聊天,JAVA-NIO实现聊天室详细代码说明

JAVA-NIO实现聊天室详细代码说明JAVA-NIO实现聊天室详细代码说明github源码&#xff1a;https://github.com/JolyouLu/JAVAIO.gitsrc\main\java\com\JolyouLu\nio\groupchat 文件夹下public class GroupChatServer {//定义属性private Selector selector;private ServerSocketC…

python如何判断是否有弹出框_Selenium2+python自动化47-判断弹出框存在(alert_is_present)【转载】...

前言系统弹窗这个是很常见的场景&#xff0c;有时候它不弹出来去操作的话&#xff0c;会抛异常。那么又不知道它啥时候会出来&#xff0c;那么久需要去判断弹窗是否弹出了。一、判断alert源码分析class alert_is_present(object):""" Expect an alert to be pre…

matlab 图像旋转补色,旋转互补色光学错觉

HTML导入代码模板&#xff1a;Choose a colorRedGreenBlueCyanMagentaYellowOrangeYellow greenCyan greenCyan blueVioletRoseOr use system color pickerComplementary color illusionInstructions Stare at the black cross in the middle of the colored circles without m…

vscode 调试_如何使用VSCode调试JS?

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;序言做前端开发的朋友经常需要使用Visual Studio Code编辑代码&#xff0c;很多朋友就想在VSCode调试JS代码&#xff0c;下面我们就介绍下如何配置操作。一、环境准备首先安装好VSCode&#xff0c;准备好一个JS项目&…

基于matlab的信号合成与分解,基于matlab的信号合成与分解

基于matlab的信号合成与分解 - I - 摘 要 为了便于进行周期信号的分析与处理&#xff0c;常要把复杂的周期信号进行分解&#xff0c;即将周期 信号分解为正余弦等此类基本信号的线性组合&#xff0c;通过对这些基本信号单元在时域和频域 特性的分析来达到了解信号特性的目的。本…

python spangt_python怎么爬去spanlt;/span中间标签的内容

展开全部这个要看你使用32313133353236313431303231363533e4b893e5b19e31333363373765的是什么页面解析工具了&#xff0c;html """item1item2"""# 使用 scrapy 的Selectorfrom scrapy.selector import Selector# scrapy 的选择器支持 css和xpa…

php页面空白如何解决,php页面空白怎么回事 php出现空白页的解决方法

当出现php空白页时&#xff0c;怎么查看php报告的错误信息呢&#xff1f;具体方法如下&#xff1a;一、通过配置 php.ini 中的参数设置php的报错级别可以在 php.ini 中适当的位置增加一行error_reporting e_all注&#xff1a; php.ini 中有一些例子&#xff0c;比如本地的 php…

基站位置查询系统_木牛导航网络基站服务免费了!——更便捷、更高效、更省心!...

布谷飞飞劝早耕&#xff0c;春锄扑扑趁初晴。千层石树通行路&#xff0c;一带水田放水声。《山行》-- 姚鼐(Photo by Quang Nguyen Vinh)农业生产作为人类最传统的产业自古以来都讲究及时耕种&#xff0c;即抢农时根据气候适宜而进行季节性生产随着科技的发展&#xff0c;农业生…

php cgi进程很多win2008,php cgi.exe 太多 在 windowserver2008 apache 这个怎么样限制下?...

php cgi.exe 太多 在 windowserver2008 apache 这个怎么样限制下&#xff1f;mip版 关注:61 答案:2 悬赏:70解决时间 2021-02-24 01:48已解决2021-02-23 09:13php cgi.exe 太多 在 windowserver2008 apache 这个怎么样限制下&#xff1f;最佳答案2021-02-23 09:57可以设置最…

wince怎么刷carplay_Carplay支持仪表/HUD显示 宝马为全球超750000辆车发布OTA升级

【太平洋汽车网 新车频道】日前&#xff0c;宝马官方宣布&#xff0c;将从10月19日起为全球超过750000辆汽车提供iDrive 7.0最新版本的最重要的一次OTA升级。据悉&#xff0c;这项升级将有多项新功能加入&#xff0c;并重点支持Apple Carplay将导航等信息显示在HUD抬头显示和全…

php 如何调用redis,php如何调用redis

一、windows下php连接redis1、下载phpredishttps://github.com/nicolasff/phpredis/downloads2、根据你php版本&#xff0c;选择安装vc库&#xff0c;可以通过phpinfo();查看3、安装php_redis.dll模块将下载下来的php_redis模块放到php安装目录下的/ext/中&#xff0c;并在php.…

文本多标签分类python_Scikitlearn多标签分类

我正在尝试使用Scikit学习来学习文本的多标签分类&#xff0c;我正在尝试调整Scikit附带的一个初始示例教程&#xff0c;用于使用wikipedia文章作为培训数据对语言进行分类。我试图在下面实现这一点&#xff0c;但代码仍然为每个返回一个标签&#xff0c;我希望最后一个预测返回…

php命令执行无法重定向输出,php – CodeIgniter 3重定向功能无法正常工作

我正在重新编码和更新我的CMS我已经在CI2工作到CI3,而在我的生活中我无法让我的重定向功能在CI3上为我工作.除了重新设计我的模型之外,我的代码到目前为止与我的CI2代码完全相同.最初我怀疑我的布局钩子是罪魁祸首,但我完全禁用了他,我仍然没有到达任何地方.public function lo…