必须使用列别名命名此表达式_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波形的图变清晰,什么修图软件能把模糊图片清晰化?

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

遗传算法在交通路线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…

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

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

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

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

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

布谷飞飞劝早耕&#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.…

分析以太网帧结构_传统以太网中的——中继器及集线器

1.1 Repeater 中继器中继器工作在以太网的第一层即物理层&#xff0c; 两端口设备&#xff0c;主要功能是放大信号&#xff0c;从而延长信号在同一网络上传输的长度。中继器的存在主要是解决解决电信号长距离传播过程中的衰减问题&#xff0c;以增加信号强度和传播距离。Figure…

html表ge模板_精选甘特图模板,丰富又好用

你听说过甘特图吗&#xff1f;你可能不知道&#xff0c;也有可能是只是听说过但是并不了解。今天我们就来说一说甘特图吧&#xff01;甘特图其实就是是通过标示出活动顺序和时间间隔来表示某一特定项目的顺序与时间之间的关系的一种图表。与时间表或日程规划表不同的部分是甘特…

oracle中调试存储过程,详解Oracle调试存储过程

详解Oracle调试存储过程一 调试关键步骤1、在要调试的存储过程右键&#xff0c;选择编辑以进行调试&#xff0c;截图如下&#xff1a;2、点击小瓢虫&#xff0c;弹出调试窗口&#xff0c;截图如下&#xff1a;3、输入7839员工编号&#xff0c;点击确认&#xff0c;进行调试&…

imp oracle full,Oracle 10g imp 之 full database (转官档)

Using Export and Import to Move a DatabaseBetweenPlatforms10g官档:The Export and Import utilities are the only method that Oracle supports for moving an existing Oracle database from one hardware platform. to another. This includes moving between UNIX and …

linux的apache安装在哪个目录,在linux系统下apache的默认安装路径在哪

如果采用RPM包安装&#xff0c;安装路径应在 /etc/httpd目录下。(学习教程推荐&#xff1a;apache)apache配置文件&#xff1a;/etc/httpd/conf/httpd.conf 可以修改相关的访问路径及配置Apache模块路径&#xff1a;/usr/sbin/apachectl 启动模块web目录&#xff1a;/var/www/h…

车子Linux系统,Linux车载系统Automotive Grade Linux

【中关村在线软件资讯】7月8日消息&#xff1a;Linux在车载系统上&#xff0c;并不想落后于苹果、谷歌等竞争对手&#xff0c;这不&#xff0c;Linux最近也推出了可定制的车载系统平台——Automotive Grade Linux&#xff0c;旨在建立一个未来智能汽车系统的标准。Linux车载系统…

linux ios开发环境,iOS开发环境搭建(Linux版)

iOS开发环境搭建(Linux版)2015-05-11 13:26:503057浏览必须申明的是&#xff0c;我们强烈建议大家在Mac下学习iOS应用开发&#xff0c;迫不得已才选择Windows和Linux。看到Linux的环境搭建步骤&#xff0c;早已凌乱。1. Ubuntu 10.10 iPhone Toolchain 4If you use Ubuntu 11.0…

pb9数据窗口中显示行数据与当前行区别_Hive的窗口函数

聚合函数&#xff08;如sum()、avg()、max()等等&#xff09;是针对定义的行集&#xff08;组&#xff09;执行聚集&#xff0c;每组只返回一个值。窗口函数也是针对定义的行集&#xff08;组&#xff09;执行聚集&#xff0c;可为每组返回多个值。如既要显示聚集前的数据,又要…