当前位置: 首页 > news >正文

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&#xff1a;条件表达式3.3 场景2&#xff1a;线程的运行表达式 1 lambda表达式 lambda表达式可以理解为匿名函数&#xff0c;也就是没有名字的函数&#xff0c;既然是函数&#…...

电梯安全监测丨S271W无线水浸传感器用于电梯机房/电梯基坑水浸监测

城市化进程中&#xff0c;电梯与我们的生活息息相关。高层住宅、医院、商场、学校、车站等各种商业体建筑、公共建筑中电梯为我们生活工作提供了诸多便利。 保障电梯系统的安全至关重要&#xff01;特别是电梯机房和电梯基坑可通过智能化改造提高其安全性和稳定性。例如在暴风…...

Java异常:基本概念、分类和处理

Java异常&#xff1a;基本概念、分类和处理 在Java编程中&#xff0c;异常处理是一个非常重要的部分。了解如何识别、处理和避免异常对于编写健壮、可维护的代码至关重要。本文将介绍Java异常的基本概念、分类和处理方法&#xff0c;并通过简单的代码示例进行说明。 一、什么…...

小谈设计模式(19)—备忘录模式

小谈设计模式&#xff08;19&#xff09;—备忘录模式 专栏介绍专栏地址专栏介绍 备忘录模式主要角色发起人&#xff08;Originator&#xff09;备忘录&#xff08;Memento&#xff09;管理者&#xff08;Caretaker&#xff09; 应用场景结构实现步骤Java程序实现首先&#xff…...

《数据库系统概论》王珊版课后习题

第一章 绪论 1.数据、数据库、数据库管理系统、数据库系统的概念 &#xff08;1&#xff09;数据&#xff08;Data&#xff09;&#xff1a;数据是数据库中存储的基本对象&#xff0c;是描述事物的符号记录。数据有多种表现形式&#xff0c;它们都可以经过数字化后存入计算机…...

MariaDB 修改用户远程登录

今天修改MariaDB数据库用户的Host时出现错误&#xff1a; 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 我的步骤如下&#xff1a; 1.登陆 2.use mysql; 3.执行…...

Elasticsearch使用mapping映射定义以及基本的数据类型

1、说明 Elasticsearch的映射相当于数据库的数据字典&#xff0c;它定义了每个字段的名称和能够保存的数据类型&#xff0c;并且内置了20多种字段类型用于支持多种多样的结构化数据&#xff0c;这里仅介绍几种常用的字段类型&#xff0c;如需要了解全部的类型&#xff0c;请参…...

【unity】制作一个角色的初始状态(左右跳二段跳)【2D横板动作游戏】

前言 hi~ 大家好&#xff01;欢迎大家来到我的全新unity学习记录系列。现在我想在2d横板游戏中&#xff0c;实现一个角色的初始状态-闲置状态、移动状态、空中状态。并且是利用状态机进行实现的。 本系列是跟着视频教程走的&#xff0c;所写也是作者个人的学习记录笔记。如有错…...

不死马的利用与克制(基于条件竞争)及变种不死马

不死马即内存马&#xff0c;它会写进进程里&#xff0c;并且无限地在指定目录中生成木马文件 这里以PHP不死马为例 测试代码&#xff1a; <?phpignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file .test.php;$code <?php if(md5($_GET["pass…...

计算机竞赛 车道线检测(自动驾驶 机器视觉)

0 前言 无人驾驶技术是机器学习为主的一门前沿领域&#xff0c;在无人驾驶领域中机器学习的各种算法随处可见&#xff0c;今天学长给大家介绍无人驾驶技术中的车道线检测。 1 车道线检测 在无人驾驶领域每一个任务都是相当复杂&#xff0c;看上去无从下手。那么面对这样极其…...

Java代理简介

代理简介 Java中的代理是一种设计模式&#xff0c;它允许一个对象&#xff08;代理对象&#xff09;代表另一个对象&#xff08;真实对象&#xff09;来控制对真实对象的访问。代理对象通常拥有与真实对象相同的接口&#xff0c;这使得客户端可以通过代理来访问真实对象&#…...

rust元组

一、元组定义 &#xff08;一&#xff09;语法 let tuple_name: (data_type1, data_type2, data_type3) (value1, value2, value3);可以不显式指定类型 let tuple_name (value1,value2,value3);使用一对小括号 () 把所有元素放在一起&#xff0c;元素之间使用逗号 , 分隔。…...

HTTPS工作过程,国家为什么让http为什么要换成https,Tomcat在MAC M1电脑如何安装,Tomcat的详细介绍

目录 引言 一、HTTPS工作过程 二、Tomcat 在访达中找到下载好的Tomcat文件夹&#xff08;这个要求按顺序&#xff09; zsh: permission denied TOMCAT的各部分含义&#xff1a; 引言 在密码中一般是&#xff1a;明文密钥->密文&#xff08;加密&#xff09; &#xff…...

第十课 贪心

文章目录 第十课 贪心lc 322.零钱兑换--中等题目描述代码展示 lc860.柠檬水找零--简单题目描述代码展示 lc455.分发饼干--简单题目描述代码展示 lc122.买卖股票的最佳时机II--中等题目描述代码展示 lc45.跳跃游戏II--中等题目描述代码展示 lc1665.完成所有任务的最少初始能量--…...

5分钟理解什么是卷积的特征提取

大家好啊&#xff0c;我是董董灿。 卷积算法之所以重要&#xff0c;关键在于其提取特征的能力。 5分钟入门卷积算法中提到&#xff0c;卷积模仿的就是人眼识图的过程&#xff0c;以“感受野”的视角去扫描图片&#xff0c;从而获取不同区域的图片信息。 在这一过程中&#x…...

Legion Y9000X IRH8 2023款(82Y3)原装出厂OEM预装Windows11系统

lenovo联想电脑笔记本拯救者原厂win11系统镜像 下载链接&#xff1a;https://pan.baidu.com/s/15G01j7ROVqOFOETccQSKHg?pwdt1ju 系统自带所有驱动、出厂主题壁纸、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;32G或以上的U盘 文件格式&#xff1a;ISO…...

【Acwing1010】拦截导弹(LIS+贪心)题解

题目描述 思路分析 本题有两问&#xff0c;第一问直接用lis的模板即可&#xff0c;下面重点看第二问 思路是贪心&#xff1a; 贪心流程&#xff1a; 从前往后扫描每一个数&#xff0c;对于每个数&#xff1a; 情况一&#xff1a;如果现有的子序列的结尾都小于当前的数&…...

DevicData-D-XXXXXXXX勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复

引言&#xff1a; 在数字时代&#xff0c;数据安全成为一项至关重要的挑战。DevicData-D-XXXXXXXX勒索病毒&#xff08;以下简称DevicData病毒&#xff09;是这场战斗中的新敌人&#xff0c;它能够以毁灭性的方式加密您的数据&#xff0c;迫使您在数据和时间之间做出艰难的选择…...

从入门到精通,30天带你学会C++【第七天:for循环和while循环以及数组的学习】(学不会你找我)

目录 Everyday English 前言 数组 数组的概念 数组的定义 数组的下标 for循环 循环是什么 基本格式 多重循环 while循环 do-while循环 总结 Everyday English To shine , not be illuminated. 去发光&#xff0c;而不是被照亮。 前言 好久不见&#xff0c…...

Python 编程基础 | 第五章-类与对象 | 5.2、数据成员

一、数据成员 数据成员是指类中定义的变量&#xff0c;即属性&#xff0c;根据定义位置&#xff0c;又可以分为类属性和实例属性&#xff0c;下面分别进行介绍。 1、实例属性 实例属性是指定义在类的方法中的属性&#xff0c;该属性属于当前实例&#xff0c;例如&#xff1a;…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...