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

详解—【C++】lambda表达式

目录

前言

一、lambda表达式

二、lambda表达式语法

2.1. lambda表达式各部分说明

2.2. 捕获列表说明

三、函数对象与lambda表达式


前言

在C++98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法。

#include <algorithm>
#include <functional>
int main()
{int array[] = { 4,1,8,5,3,7,0,9,2,6 };// 默认按照小于比较,排出来结果是升序std::sort(array, array + sizeof(array) / sizeof(array[0]));// 如果需要降序,需要改变元素的比较规则std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());return 0;
}

如果待排序元素为自定义类型,需要用户定义排序时的比较规则:

struct Goods
{string _name;double _price;
};
struct Compare
{bool operator()(const Goods& gl, const Goods& gr){return gl._price <= gr._price;}
};
int main()
{Goods gds[] = { { "苹果", 2.1 }, { "相交", 3 }, { "橙子", 2.2 }, {"菠萝", 1.5} };sort(gds, gds + sizeof(gds) / sizeof(gds[0]), Compare());return 0;
}

随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法, 都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,这些都给编程者带来了极大的不便。因此,在C11语法中出现了Lambda表达式。

一、lambda表达式

int main()
{Goods gds[] = { { "苹果", 2.1 }, { "相交", 3 }, { "橙子", 2.2 }, {"菠萝", 1.5} };sort(gds, gds + sizeof(gds) / sizeof(gds[0]), [](const Goods& l, const Goods& r)->bool{return l._price < r._price;});return 0;
}

上述代码就是使用C++11中的lambda表达式来解决,可以看出lamb表达式实际是一个匿名函数。
 

二、lambda表达式语法

lambda表达式书写格式:[capture-list] (parameters) mutable -> return-type { statement }

2.1. lambda表达式各部分说明
 

[capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。

(parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略

mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。

->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。

{statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

注意: 在lambda函数定义中,参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为空。因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

int main()
{// 最简单的lambda表达式, 该lambda表达式没有任何意义[] {};// 省略参数列表和返回值类型,返回值类型由编译器推导为intint a = 3, b = 4;[=] {return a + 3; };// 省略了返回值类型,无返回值类型auto fun1 = [&](int c) {b = a + c; };fun1(10)cout << a << " " << b << endl;// 各部分都很完善的lambda函数auto fun2 = [=, &b](int c)->int {return b += a + c; };cout << fun2(10) << endl;// 复制捕捉xint x = 10;auto add_x = [x](int a) mutable { x *= 2; return a + x; };cout << add_x(10) << endl;return 0;
}

通过上述例子可以看出,lambda表达式实际上可以理解为无名函数,该函数无法直接调用,如果想要直接调用,可借助auto将其赋值给一个变量。
 

2.2. 捕获列表说明

捕捉列表描述了上下文中那些数据可以被lambda使用,以及使用的方式传值还是传引用。

[var]:表示值传递方式捕捉变量var
[=]:表示值传递方式捕获所有父作用域中的变量(包括this)
[&var]:表示引用传递捕捉变量var
[&]:表示引用传递捕捉所有父作用域中的变量(包括this)
[this]:表示值传递方式捕捉当前的this指针

注意:

a. 父作用域指包含lambda函数的语句块

b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割

比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量 [&,a, this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量 c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重

d. 在块作用域以外的lambda函数捕捉列表必须为空。


e. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局

部变量都会导致编译报错。

f. lambda表达式之间不能相互赋值,即使看起来类型相同

void (*PF)();
int main()
{auto f1 = [] {cout << "hello world" << endl; };auto f2 = [] {cout << "hello world" << endl; };// 此处先不解释原因,等lambda表达式底层实现原理看完后,大家就清楚了//f1 = f2; // 编译失败--->提示找不到operator=()// 允许使用一个lambda表达式拷贝构造一个新的副本auto f3(f2);f3();// 可以将lambda表达式赋值给相同类型的函数指针PF = f2;PF();return 0;
}

三、函数对象与lambda表达式

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的类对象。

class Rate
{
public:Rate(double rate) : _rate(rate){}double operator()(double money, int year){return money * _rate * year;}
private:double _rate;
};
int main()
{// 函数对象double rate = 0.49;Rate r1(rate);r1(10000, 2);// lamberauto r2 = [=](double monty, int year)->double {return monty * rate * year; };r2(10000, 2);return 0;
}

从使用方式上来看,函数对象与lambda表达式完全一样。

函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可以直接将该变量捕获到

实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator()。

相关文章:

详解—【C++】lambda表达式

目录 前言 一、lambda表达式 二、lambda表达式语法 2.1. lambda表达式各部分说明 2.2. 捕获列表说明 三、函数对象与lambda表达式 前言 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。 #include <algorithm> #i…...

Qt Desktop Widgets 控件绘图原理逐步分析拆解

Qt 是目前C语言首选的框架库。之所以称为框架库而不单单是GUI库&#xff0c;是因为Qt提供了远远超过GUI的功能封装&#xff0c;即使不使用GUI的后台服务&#xff0c;也可以用Qt大大提高跨平台的能力。 仅就界面来说&#xff0c;Qt 保持各个平台绘图等效果的统一&#xff0c;并…...

什么是rocketmq❓

在大规模分布式系统中&#xff0c;各个服务之间的通信是至关重要的&#xff0c;而RocketMQ作为一款分布式消息中间件&#xff0c;为解决这一问题提供了强大的解决方案。本文将深入探讨RocketMQ的基本概念、用途&#xff0c;以及在实际分布式系统中的作用&#xff0c;并对Produc…...

【网络安全】HTTP Slowloris攻击原理解析

文章目录 Slowloris攻击的概念Slowloris攻击原理Slowloris攻击的步骤其他的DDoS攻击类型UDP FloodICMP (Ping) FloodSYN FloodPing of DeathNTP AmplificationHTTP FloodZero-day DDoS 攻击 推荐阅读 Slowloris攻击的概念 Slowloris是在2009年由著名Web安全专家RSnake提出的一…...

从最近爆火的ChatGPT,我看到了电商的下一个形态

爆火的ChatGPT似乎让每个行业有了改造的可能性&#xff0c;电商行业也不例外。 在讨论了很多流量红利消失的话题后&#xff0c;我们看到互联网电商行业不再性感&#xff0c;从淘宝天猫&#xff0c;京东&#xff0c;到拼多多&#xff0c;再到抖音&#xff0c;快手&#xff0c;电…...

云原生向量计算引擎 PieCloudVector:为大模型提供独特记忆

拓数派大模型数据计算系统&#xff08;PieDataComputingSystem&#xff0c;缩写&#xff1a;πDataCS&#xff09;在10月24日程序员节「大模型数据计算系统」2023拓数派年度技术论坛正式发布。πDataCS 以云原生技术重构数据存储和计算&#xff0c;「一份存储&#xff0c;多引擎…...

大创项目推荐 深度学习 opencv python 实现中国交通标志识别

文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 &#x1f525; 优质…...

深度学习实战67-基于Stable-diffusion的图像生成应用模型的搭建,在Kaggle平台的搭建部署,解决本地没有算力资源问题

大家好,我是微学AI,今天给大家介绍一下深度学习实战67-基于Stable-diffusion的图像生成应用模型的搭建,在Kaggle平台的搭建部署,解决本地没有算力资源问题。稳定扩散模型(Stable Diffusion Model)是一种用于图像增强和去噪的计算机视觉算法。它通过对输入图像进行扩散过程…...

云原生之深入解析Kubernetes本地持久化存储方案OpenEBS LocalPV的最佳实践

一、K8s 本地存储 K8s 支持多达 20 种类型的持久化存储&#xff0c;如常见的 CephFS 、Glusterfs 等&#xff0c;不过这些大都是分布式存储&#xff0c;随着社区的发展&#xff0c;越来越多的用户期望将 K8s 集群中工作节点上挂载的数据盘利用起来&#xff0c;于是就有了 loca…...

设计模式-策略(Strategy)模式

又被称为政策&#xff08;方针&#xff09;模式策略模式(Strategy Design Pattern)&#xff1a;封装可以互换的行为&#xff0c;并使用委托来决定要使用哪一个策略模式是一种行为设计模式&#xff0c;它能让你定义一系列算法&#xff0c;并将每种算法分别放入独立的类中&#x…...

Star 4.1k!Gitee GVP开源项目!新一代桌面应用开发框架 ElectronEgg!

前言 随着现代技术的快速升级迭代及发展&#xff0c;桌面应用开发已经变得越来越普及。然而对于非专业桌面应用开发工程师在面对这项任务时&#xff0c;可能会感到无从下手&#xff0c;甚至觉得这是一项困难的挑战。 本篇文章将分享一种新型桌面应用开发框架 ElectronEgg&…...

node.js学习(简单聊天室)

在掘金查看该文章 1. TCP服务搭建 1.1 socket 先来粗略了解下socket 套接字&#xff08;socket&#xff09;是一个抽象层&#xff0c;应用程序可以通过它发送或接收数据&#xff0c;可对其进行像对文件一样的打开、读写和关闭等操作。套接字允许应用程序将I/O插入到网络中&am…...

cfa一级考生复习经验分享系列(四)

备考CFA一级满打满算用了一个多月&#xff0c;每天八个小时以上。可能如果仅以通过为目标的话完全不用这样&#xff0c;看过太多类似于只看了一周就通过了考试又或是放弃了好几门飘过了考试的情况&#xff0c;我觉得这是不正确的考试状态&#xff0c;完全不必惊叹&#xff0c;踏…...

PPT插件-好用的插件-放映笔、绘图板-大珩助手

放映笔 幻灯片放映时&#xff0c;工具在幻灯片的左下方&#xff0c;本工具在幻灯片的右侧&#xff0c;可以移动&#xff0c;可以方便在右侧讲课时候使用 绘图板 可在绘图板上写签名、绘制图画、写字等等&#xff0c;点画笔切换橡皮擦&#xff0c;点插入绘图&#xff0c;将背景…...

弧形导轨的安装注意事项

随着弧形导轨的应用日渐普遍&#xff0c;在日常使用中总会遇到很多各种各样的问题&#xff0c;原因很多是安装不正确或者使用不恰当。不合理的使用不但不能充分发挥其价值还会导致使用寿命大打折扣&#xff0c;使企业造成不必要的损失&#xff0c;因此大伙有必要了解一些安装的…...

Elasticsearch优化-04

Elasticsearch优化 1、优化-硬件选择 Elasticsearch 的基础是 Lucene&#xff0c;所有的索引和文档数据是存储在本地的磁盘中&#xff0c;具体的路径可在 ES 的配置文件…/config/elasticsearch.yml中配置&#xff0c;如下&#xff1a; # #Path to directory where to store …...

Springboot+vue的公寓报修管理系统(有报告)。Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的公寓报修管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的公寓报修管理系统&#xff0c;采用M&#xff08;model&…...

uniapp腾讯地图路线规划

在uniapp中使用腾讯地图进行路线规划需要通过腾讯地图API进行操作。以下是基本的步骤&#xff1a; 在腾讯地图开放平台上注册账号&#xff0c;并创建应用获取API key。 在uniapp的项目中引入腾讯地图API的JS文件&#xff0c;例如在index.html中添加以下代码&#xff1a; <…...

Python 全栈体系【四阶】(五)

第四章 机器学习 三、数据预处理 1. 数据预处理的目的 去除无效数据、不规范数据、错误数据 补齐缺失值 对数据范围、量纲、格式、类型进行统一化处理&#xff0c;更容易进行后续计算 2. 预处理方法 2.1 标准化&#xff08;均值移除&#xff09; 让样本矩阵中的每一列的…...

原点处可微问题

文章目录 原点可微问题例例 原点可微问题 lim ⁡ x → 0 , y → 0 f ( x , y ) − f ( 0 , 0 ) x 2 y 2 \lim\limits_{x\to{0},y\to{0}} \frac{f(x,y)-f(0,0)}{\sqrt{x^2y^2}} x→0,y→0lim​x2y2 ​f(x,y)−f(0,0)​ 0 0 0(1)是函数 f ( x , y ) f(x,y) f(x,y)在 ( 0 , 0 ) (…...

Taotoken在数据预处理与分析脚本中调用大模型的集成案例

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken在数据预处理与分析脚本中调用大模型的集成案例 应用场景类&#xff0c;设想一个数据科学家使用Python脚本进行数据分析时…...

终极指南:用ContextMenuManager彻底解决Windows右键菜单混乱问题

终极指南&#xff1a;用ContextMenuManager彻底解决Windows右键菜单混乱问题 【免费下载链接】ContextMenuManager &#x1f5b1;️ 纯粹的Windows右键菜单管理程序 项目地址: https://gitcode.com/gh_mirrors/co/ContextMenuManager 你是否曾因Windows右键菜单过于臃肿…...

从零到一:手把手教你用LabelImg高效构建VOC与YOLO数据集

1. 为什么你需要掌握LabelImg标注工具 刚接触计算机视觉时&#xff0c;我最头疼的就是数据准备环节。记得第一次尝试训练目标检测模型&#xff0c;花了两周时间收集了上千张图片&#xff0c;却在标注环节卡住了——手动画框太慢&#xff0c;格式转换出错&#xff0c;反复返工差…...

ARM调试异常与调试状态机制详解

1. ARM调试异常机制深度解析调试异常是ARM处理器调试体系中的核心机制&#xff0c;当处理器在监控调试模式(Monitor debug-mode)下发生特定调试事件时触发。理解这一机制对于嵌入式系统开发至关重要&#xff0c;它直接影响着断点设置、单步调试等基础调试功能的实现效果。1.1 调…...

ArcGIS标注进阶:手把手教你搞定分式标注和河流左斜体(附完整表达式)

ArcGIS标注进阶&#xff1a;分式标注与河流左斜体实战指南 在地图制图领域&#xff0c;专业标注是提升可视化效果的关键环节。许多GIS工程师在进行水文地质制图时&#xff0c;常遇到分式标注格式混乱、河流名称无法实现标准左斜体等痛点问题。本文将彻底解决这些标注难题&#…...

给视觉开发新手的保姆级教程:在Ubuntu上从下载源码到成功运行Demo,搞定OpenCV 3环境搭建

给视觉开发新手的保姆级教程&#xff1a;在Ubuntu上从下载源码到成功运行Demo&#xff0c;搞定OpenCV 3环境搭建 第一次在Ubuntu上搭建OpenCV开发环境&#xff0c;对很多视觉开发新手来说可能是个令人望而生畏的任务。命令行操作、编译工具链、环境配置……这些术语听起来就让人…...

2026最权威的AI辅助写作方案推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在当下的学术环境里头&#xff0c;知网的AI内容识别机制已然全面实现落地&#xff0c;针对由…...

Flutter从入门到实战-02-Flutter框架核心

Flutter 从入门到实战&#xff08;二&#xff09;&#xff1a;Flutter 框架核心本文根据讲义目标是把“会搭环境、会写页面、会管理状态与路由、会做基础网络请求”串成一条完整上手路径。一、先把开发环境一次搭对 这部分讲义强调的核心思想是&#xff1a;环境问题越早解决&am…...

原来Ilya还有70亿美元OpenAI股权

鹭羽 发自 凹非寺量子位 | 公众号 QbitAI马斯克 VS 奥特曼的世纪庭审&#xff0c;也太劲爆了——感觉自己像是瓜田里的猹&#xff0c;一瓜未平一瓜又起。吃不过来&#xff0c;根本吃不过来……这不&#xff0c;就在刚刚&#xff0c;OpenAI的造富神话被「一不小心」炸了出来。Op…...

通过Taotoken用量看板清晰掌握团队的大模型API消费情况

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 通过Taotoken用量看板清晰掌握团队的大模型API消费情况 对于团队管理者或项目负责人而言&#xff0c;在引入大模型能力后&#xff…...