c++的lambda表达式
文章目录
- 1 lambda表达式
- 2 捕捉列表 vs 参数列表
- 3 lambda表达式的传递
- 3.1 函数作为形参
- 3.2 场景1:条件表达式
- 3.3 场景2:线程的运行表达式
1 lambda表达式
lambda表达式可以理解为匿名函数,也就是没有名字的函数,既然是函数,那也遵循函数使用的一些规则,例如,传参方式等。
lambda表达式的一般形式是:
[捕捉列表] (参数列表) mutable -> 返回值类型 { 函数体 }
捕捉列表:跟参数列表有些类似,可以用于访问外部的变量
参数列表:函数的参数,支持使用值传递和引用传递,如果没有参数,可以省略
mutable:默认情况下,通过值传递的捕捉列表参数
是只读的,也就是不允许进行修改,类似于const,可以通过加上mutable关键字,表明在表达式中会对该变量进行修改
返回值类型:通常不用写,让编译器直接推导返回值类型
函数体:使用捕捉列表和参数列表进行计算,得到返回值
[] {cout << "hell" << endl;
}
上面就是一个最简单的lambda表达式,lambda表达式从行为和形式上都像函数,而且调用方式也很像。
auto func = [] {cout << "hell" << endl;
};func();
将lambda表达式给到变量func,然后就可以将它当做一个函数执行。
2 捕捉列表 vs 参数列表
捕捉列表和参数列表都可以传递外部的变量,并且都支持值传递和引用传递,例如:
#include <iostream>
using namespace std;int main() {int a = 1;int b = 2;auto l = [&a](int &b) {++a;++b;};l(b);cout << "a=" << a << endl;cout << "b=" << b << endl;return 0;
}
采用引用传递分别给到捕捉列表和参数列表,然后在lambda表达式内部修改变量的值,最后在lambda表达式外部打印变量的值,可以看到采用捕捉列表和参数列表达到了相同的效果,都对环境中的变量进行了修改。当然,也会发现两者的不同:使用捕捉列表时,在定义时指定变量,在调用时就不用指定;使用参数列表,在定义时只是指定类型,在调用时需要传参。
因此,捕捉列表相当于在对象构造函数阶段将外部的变量放到了对象的内部,作为初始化的一种手段;而参数列表相当于是在调用对象的operator()方法时给的参数。两者赋值的时机有所不同,而且,对于捕捉列表来说,在定义lambda表达式时就知道用的变量是什么,而参数列表是需要在调用传递参数时才知道用的变量是什么。
3 lambda表达式的传递
使用lambda表达式当然不是为了作为函数调用,普通的函数和内联函数可以满足需求,使用lambda表达式通常是为了将lambda表达式作为条件或者执行逻辑传递出去。
3.1 函数作为形参
#include <iostream>
using namespace std;typedef void (*print)(std::string);void func(print pfunc) {pfunc("hello");
}int main() {int a = 1;int b = 2;auto l = [](std::string msg) {cout << msg << endl;};func(l);return 0;
}
首先定义print类型的函数指针,然后定义了func函数,它接受print类型的参数,然后调用它,而在主函数中,定义了接受相同形参的lambda表达式,然后传给func函数。
上面的函数指针定义在C中比较常见,而在C++中通常会使用std::function:
#include <iostream>
#include <functional>
using namespace std;void func(std::function<void(std::string)> pfunc) {pfunc("luofeng");
}int main() {int a = 1;int b = 2;auto l = [](std::string msg) {cout << msg << endl;};func(l);return 0;
}
在定义函数时形参直接通过std::function给出,而不用额外定义函数指针,调用方式跟之前的函数指针一样。
上面就是将lambda当做函数传递的示例,在实际使用中,比较常见的有下面两种场景。
3.2 场景1:条件表达式
#include <iostream>
#include <set>
using namespace std;int main() {auto cmp = [](int lh, int rh) {return lh > rh;};set<int, decltype(cmp)> my_set(cmp);my_set.emplace(2);my_set.emplace(5);for(const auto& element: my_set) {cout << element << " ";}return 0;
}
std::set的第二个模板参数是一个比较函数,在这里先定义了一个lambda表达式cmp,然后用cmp来定义my_set,然后向set中插入元素,最后再遍历,这里有几个点需要注意:
- std::set的第二个模板参数是个函数指针,也就是函数类型,而lambda表达式是个对象,因此,需要用decltype获取lambda表达式的类型,因为lambda表达式的类型是编译器自己生成的,为了能够在代码中方便获取类型,C++11提供了decltype获取lambda的类型
- std::set的构造函数需要指定实际的比较函数,因此,这里传递lambda变量
- 向std::set中插入元素使用的是emplace,而不是通常的insert,两者的区别在于,使用insert时,会先构造一个临时对象,然后调用临时对象的拷贝构造函数在std::set中创建对象,而使用emplace时,可以直接使用参数在std::set中创建对象,减少一次拷贝构造函数的调用,当然,这里的类型是int,用insert和emplace就没啥区别
3.3 场景2:线程的运行表达式
C++11中引入了std::thread在语言级别支持线程:
#include <iostream>
#include <thread>
using namespace std;int main() {thread t([](int loop) {while(--loop) {cout << this_thread::get_id() << " " << loop << endl;};}, 10);t.join();
}
首先使用thread创建一个线程,线程的构造函数接受两个参数,一个是函数,另一个是参数列表,这里用lambda表达式提供函数,lambda表达式有一个整型参数,然后将参数列表设置为10,作为lambda表达式的参数,最后调用thread的join等待线程执行结束。
这里还使用了std::this_thread这个ns中的get_id()来获取线程ID,在std::this_thread中有4个函数:
- get_id():获取线程ID
- yield():让出CPU
- sleep_until():阻塞当前线程,休眠直到某个时间点
- sleep_for():阻塞当前线程,休眠一段时间
而std::thread类提供的函数主要有以下几个:
- get_id():获取线程ID
- join():启动线程,并等待线程执行结束
- detach():线程就成为后台的守护线程
相关文章:
c++的lambda表达式
文章目录 1 lambda表达式2 捕捉列表 vs 参数列表3 lambda表达式的传递3.1 函数作为形参3.2 场景1:条件表达式3.3 场景2:线程的运行表达式 1 lambda表达式 lambda表达式可以理解为匿名函数,也就是没有名字的函数,既然是函数&#…...
电梯安全监测丨S271W无线水浸传感器用于电梯机房/电梯基坑水浸监测
城市化进程中,电梯与我们的生活息息相关。高层住宅、医院、商场、学校、车站等各种商业体建筑、公共建筑中电梯为我们生活工作提供了诸多便利。 保障电梯系统的安全至关重要!特别是电梯机房和电梯基坑可通过智能化改造提高其安全性和稳定性。例如在暴风…...
Java异常:基本概念、分类和处理
Java异常:基本概念、分类和处理 在Java编程中,异常处理是一个非常重要的部分。了解如何识别、处理和避免异常对于编写健壮、可维护的代码至关重要。本文将介绍Java异常的基本概念、分类和处理方法,并通过简单的代码示例进行说明。 一、什么…...
小谈设计模式(19)—备忘录模式
小谈设计模式(19)—备忘录模式 专栏介绍专栏地址专栏介绍 备忘录模式主要角色发起人(Originator)备忘录(Memento)管理者(Caretaker) 应用场景结构实现步骤Java程序实现首先ÿ…...
《数据库系统概论》王珊版课后习题
第一章 绪论 1.数据、数据库、数据库管理系统、数据库系统的概念 (1)数据(Data):数据是数据库中存储的基本对象,是描述事物的符号记录。数据有多种表现形式,它们都可以经过数字化后存入计算机…...
MariaDB 修改用户远程登录
今天修改MariaDB数据库用户的Host时出现错误: ERROR 1356 (HY000): View ‘mysql.user’ references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them 我的步骤如下: 1.登陆 2.use mysql; 3.执行…...
Elasticsearch使用mapping映射定义以及基本的数据类型
1、说明 Elasticsearch的映射相当于数据库的数据字典,它定义了每个字段的名称和能够保存的数据类型,并且内置了20多种字段类型用于支持多种多样的结构化数据,这里仅介绍几种常用的字段类型,如需要了解全部的类型,请参…...
【unity】制作一个角色的初始状态(左右跳二段跳)【2D横板动作游戏】
前言 hi~ 大家好!欢迎大家来到我的全新unity学习记录系列。现在我想在2d横板游戏中,实现一个角色的初始状态-闲置状态、移动状态、空中状态。并且是利用状态机进行实现的。 本系列是跟着视频教程走的,所写也是作者个人的学习记录笔记。如有错…...
不死马的利用与克制(基于条件竞争)及变种不死马
不死马即内存马,它会写进进程里,并且无限地在指定目录中生成木马文件 这里以PHP不死马为例 测试代码: <?phpignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file .test.php;$code <?php if(md5($_GET["pass…...
计算机竞赛 车道线检测(自动驾驶 机器视觉)
0 前言 无人驾驶技术是机器学习为主的一门前沿领域,在无人驾驶领域中机器学习的各种算法随处可见,今天学长给大家介绍无人驾驶技术中的车道线检测。 1 车道线检测 在无人驾驶领域每一个任务都是相当复杂,看上去无从下手。那么面对这样极其…...
Java代理简介
代理简介 Java中的代理是一种设计模式,它允许一个对象(代理对象)代表另一个对象(真实对象)来控制对真实对象的访问。代理对象通常拥有与真实对象相同的接口,这使得客户端可以通过代理来访问真实对象&#…...
rust元组
一、元组定义 (一)语法 let tuple_name: (data_type1, data_type2, data_type3) (value1, value2, value3);可以不显式指定类型 let tuple_name (value1,value2,value3);使用一对小括号 () 把所有元素放在一起,元素之间使用逗号 , 分隔。…...
HTTPS工作过程,国家为什么让http为什么要换成https,Tomcat在MAC M1电脑如何安装,Tomcat的详细介绍
目录 引言 一、HTTPS工作过程 二、Tomcat 在访达中找到下载好的Tomcat文件夹(这个要求按顺序) zsh: permission denied TOMCAT的各部分含义: 引言 在密码中一般是:明文密钥->密文(加密) ÿ…...
第十课 贪心
文章目录 第十课 贪心lc 322.零钱兑换--中等题目描述代码展示 lc860.柠檬水找零--简单题目描述代码展示 lc455.分发饼干--简单题目描述代码展示 lc122.买卖股票的最佳时机II--中等题目描述代码展示 lc45.跳跃游戏II--中等题目描述代码展示 lc1665.完成所有任务的最少初始能量--…...
5分钟理解什么是卷积的特征提取
大家好啊,我是董董灿。 卷积算法之所以重要,关键在于其提取特征的能力。 5分钟入门卷积算法中提到,卷积模仿的就是人眼识图的过程,以“感受野”的视角去扫描图片,从而获取不同区域的图片信息。 在这一过程中&#x…...
Legion Y9000X IRH8 2023款(82Y3)原装出厂OEM预装Windows11系统
lenovo联想电脑笔记本拯救者原厂win11系统镜像 下载链接:https://pan.baidu.com/s/15G01j7ROVqOFOETccQSKHg?pwdt1ju 系统自带所有驱动、出厂主题壁纸、Office办公软件、联想电脑管家等预装程序 所需要工具:32G或以上的U盘 文件格式:ISO…...
【Acwing1010】拦截导弹(LIS+贪心)题解
题目描述 思路分析 本题有两问,第一问直接用lis的模板即可,下面重点看第二问 思路是贪心: 贪心流程: 从前往后扫描每一个数,对于每个数: 情况一:如果现有的子序列的结尾都小于当前的数&…...
DevicData-D-XXXXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
引言: 在数字时代,数据安全成为一项至关重要的挑战。DevicData-D-XXXXXXXX勒索病毒(以下简称DevicData病毒)是这场战斗中的新敌人,它能够以毁灭性的方式加密您的数据,迫使您在数据和时间之间做出艰难的选择…...
从入门到精通,30天带你学会C++【第七天:for循环和while循环以及数组的学习】(学不会你找我)
目录 Everyday English 前言 数组 数组的概念 数组的定义 数组的下标 for循环 循环是什么 基本格式 多重循环 while循环 do-while循环 总结 Everyday English To shine , not be illuminated. 去发光,而不是被照亮。 前言 好久不见,…...
Python 编程基础 | 第五章-类与对象 | 5.2、数据成员
一、数据成员 数据成员是指类中定义的变量,即属性,根据定义位置,又可以分为类属性和实例属性,下面分别进行介绍。 1、实例属性 实例属性是指定义在类的方法中的属性,该属性属于当前实例,例如:…...
PHP 个人愿望众筹网站系统mysql数据库web结构apache计算机软件工程网页wamp
一、源码特点 PHP 个人愿望众筹网站系统是一套完善的web设计系统,对理解php编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 php 个人愿望众筹网站 代码 https://download.csdn.net/download/qq_41221322/8…...
JS--判断空值(null、undefined、NaN、false、空字符串等)
原文网址:JS--判断空值(null、undefined、NaN、false、空字符串等)_IT利刃出鞘的博客-CSDN博客 简介 本文介绍JavaScript判断空值的方法。 空值包括:undefined,null,NaN,,false,{}࿰…...
ChatGPT 背后包含了哪些技术?
ChatGPT 是由OpenAI开发的一款基于GPT-3(Generative Pre-trained Transformer 3)的人工智能语言模型。这个模型是使用多种编程语言和技术组合编写的。 首先,ChatGPT 使用了 Python 作为主要的编程语言。Python 是一种流行的高级编程语言&…...
Vue Router(二)
目录 一、嵌套路由 1、路由定义 2、代码例子 3、重定向 二、懒加载 1、缘由 2、代码例子 三、导航守卫 1、全局前置守卫 2、全局后置守卫 3、meta元信息 四、生命周期 1、解释 2、执行顺序 3、例子 五、keep-alive组件缓存(保活) 1、介…...
ELK整合springboot(第二课)
一、创建一个springboot的项目 pom文件如下: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLo…...
运维常见的22个故障排查和10个问题解决技巧大汇总!
作为运维,多多少少会碰见这样那样的问题或故障,从中总结经验,查找问题,汇总并分析故障的原因,这是一个运维工程师良好的习惯。每一次技术的突破,都经历着苦闷,伴随着快乐,可我们还是…...
解决 TensorFlow 2.x 中的 “AttributeError: module ‘tensorflow‘ has no attribute ‘placeholder‘“ 错误
项目场景: 在使用 TensorFlow 框架实现深度学习应用时,可能会遇到以下错误: AttributeError: module tensorflow has no attribute placeholder问题描述 在 TensorFlow 1.x 版本中,placeholder 函数用于创建占位符张量。然而&a…...
新风机注意事项有哪些?
选择和使用新风机时,有几个关键注意事项需要牢记: 安装位置:新风机的安装位置很重要。通常情况下,应将其安装在室外以避免室内产生噪音和减少室内的体积占据。确保选择合适的安装位置,以便新风机能够顺利引入新鲜空气。…...
GitHub基础
1、仓库是什么意思?仓库拥有者是谁? 在软件开发或版本控制系统中,"仓库"(Repository)是指存储项目代码、配置文件、文档等相关文件的地方。它可以看作是一个中央存储库,用于管理和跟踪项目的各个…...
读书笔记--未来简史关键金句和阅读感悟
借着国庆假期,终于有时间研读了尤瓦尔.赫拉利的《未来简史》,作者的写作方式、文笔、观察视角都是我喜欢的类型,作者从古到今,谈到了上帝、神、宗教、科技、生物、智人到未来的超人智神(数据主义)ÿ…...
wordpress插件的用法/百度发视频步骤
父组件向子组件传值:父组件通过属性向下传值的方式和子组件通信;使用步骤:定义组件:现有自定义组件com-a、com-b,com-a是com-b的父组件;准备获取数据:com-b要获取父组件data中的name属性&#x…...
网站建设狼雨/小说排行榜2020前十名
通用的语言有很多种,例如英语和中文,在网络的通讯中,通用的协议有很多,其中http是被最广泛使用的。如果是私有的协议,那就只能自己设计了。 用http是最方便的,如果是私有协议,包含协议的封装和拆…...
网站做乘法表/手机百度免费下载
在 Rss Bandit 和 SharpDevelop 之间的权衡 在 Rss Bandit 和 SharpDevelop 之间的权衡 (心理变化过程,没有技术含量,只是胡诌,呵呵) 距离上次的WebLog居然过了一个月有半,其实心理是一直希望可以经常写点…...
网站制作网站/深圳优化公司
在Qtpro文件中添加Qtgui QImage的帮助中写的很清楚 Header: #include <QImage> qmake: QT gui...
网站建设与优化合同/百度指数查询app
进程间通信——命名管道命名管道命名管道的创建命令创建函数创建特性命名管道 和匿名管道一样,命名管道也是在内核中开辟的一段缓存区,不过和匿名管道不同的是,这段缓存区是有标识符的,这也就意味着不同的进程,不需要…...
joomla 网站建设教程/代运营公司哪家好一些
11.25事物隔离级别事物日志redo undo事物锁 begin; update事物日志性能优化 innodb_flush_log_at_trx_commit0|1|2|3innodb事务日志相关配置; show variables like %innodb_log%;通用日志通用日志:记录对数据库的通用操作,包括错误的SQL语句通…...