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

lambda表达式 - c++11

文章目录:

  • lambda表达式概念
  • lambda表达式语法
  • 函数对象与lambda表达式

lambda表达式概念

lambda 表达式是 c++11 中引入的一种匿名函数,它可以在需要函数对象的地方使用,可以用作函数参数或返回值。lambda 表达式可以看作是一种局部定义的函数对象,它通常用于简化代码或实现某些特定的功能。

接下来我们举一个例子来说明为什么需要 lambda 表达式:

商品类 Goods 的定义:

struct Goods
{string _name;  // 名字double _price; // 价格int _count;    // 数量
};

现在,我们需要对若干商品分别按照价格和数量进行升序、降序排序。

想要对一个数据集合中的元素进行排序,可以使用 sort 函数,但是这里的待排序元素是自定义类型,因此需要用户自定义排序的比较规则。控制 sort 函数的比较方式通常有两种方法:1. 对商品类的 () 运算符进行重载; 2. 通过仿函数指定比较方式。

下面使用仿函数的方式来完成上述的排序:

struct Goods
{Goods(const char* str, double price, int count):_name(str),_price(price),_count(count){}string _name;double _price;int _count;
};struct ComparePriceLess
{bool operator()(const Goods& gl, const Goods& gr){return gl._price < gr._price;}
};struct ComparePriceGreater
{bool operator()(const Goods& gl, const Goods& gr){return gl._price > gr._price;}
};struct CompareNumLess
{bool operator()(const Goods& gl, const Goods& gr){return gl._count < gr._count;}
};struct CompareNumGreater
{bool operator()(const Goods& gl, const Goods& gr){return gl._count > gr._count;}
};int main()
{vector<Goods> v = { { "苹果", 2.1, 50 }, { "香蕉", 3, 40 }, { "草莓", 2.2,30 }, { "菠萝", 1.5, 40 },{"芒果",2.5,120} };sort(v.begin(), v.end(), ComparePriceLess());sort(v.begin(), v.end(), ComparePriceGreater());sort(v.begin(), v.end(), CompareNumLess());      sort(v.begin(), v.end(), CompareNumGreater()); 
}

使用仿函数可以解决自定义类型的排序问题,在大型项目中,有可能仿函数的定义位置和使用仿函数的位置可能会相隔很远,所以仿函数的命令必须要通俗易懂,否则会降低代码的可读性和可维护性。

随着 c++ 语法的发展,人们觉得上面的写法太复杂了,每次为了实现一个 algorithm 算法,都需要重新去写一个类,如果每次比较的逻辑不一样,还需要去实现多个类,特别是相同类的命名。因此,c++11 中出现了 lambda 表达式。

使用 lambda 表达式完成上面要求,如下:

struct Goods
{Goods(const char* str, double price, int count):_name(str),_price(price),_count(count){}string _name;double _price;int _count;
};int main()
{vector<Goods> v = { { "苹果", 2.1, 50 }, { "香蕉", 3, 40 }, { "草莓", 2.2,30 }, { "菠萝", 1.5, 40 },{"芒果",2.5,120} };sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price < g2._price;});sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price > g2._price;});sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._count < g2._count;});sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._count > g2._count;});
}

在这个代码示例中,使用 lambda 表达式作为 sort 函数的第三个参数,可以方便地根据不同的排序标准对 vector 中的 Goods 对象进行排序,而不需要单独定义多个比较函数。这样可以减少代码量和提高代码的可读性,同时节省定义函数的时间和空间开销。

lambda表达式语法

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

  • [capture-list]:捕捉列表,该列表位于 lambda 函数的开始位置,编译器根据 [] 来判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上下文中的变量供 lambda 函数使用。
  • (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同 () 一起省略。
  • mutable:默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  • returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
  • {statement}:函数体。在该函数体内,处理可以使用其参数外,还可以使用所有捕获到的变量。

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

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

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

说明:

  • 父作用域指包含 lambda 函数的语句块。
  • 语法上捕捉列表可由多个捕捉项组成,并以逗号分隔。 如:[=,&a,&b] 以引用传递的方式捕捉变量 a 和 b,指传递方式捕捉其它所有变量,[&,a,this] 值传递方式捕捉变量 a 和 this,引用方式捕捉其它变量。
  • 捕捉列表不允许变量重复传递,否则会导致编译报错。 如:[=,a]:= 已经以值传递方式捕捉了所有变量,捕捉 a 重复了。
  • 在块作用域以外的 lambda 函数捕捉列表必须为空。
  • 在块作用域中的 lambda 函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错。
  • lambda 表达式之间不能相互赋值,即使看起来类型相同。

lambda 表达式使用示例:

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

以下代码演示了 lambda 函数的拷贝构造以及如何将 lambda 表达式赋值给函数指针:

void (*pfunc)();int main()
{auto f1 = [] {cout << "lambda" << endl;};auto f2 = [] {cout << "lambda" << endl;};// f1 = f2; // 编译失败,提示找不到operator=()// 允许使用一个lambda表达式拷贝构造一个新的副本auto f3(f2);f3();// 可以将lambda表达式赋值给相同类型的函数指针pfunc = f2;pfunc();return 0;
}

函数对象与lambda表达式

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

如下所示,分别使用函数对象和 lambda 表达式实现计算利息:

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);// lambdaauto r2 = [=](double monty, int year)->double {return monty * rate * year;};r2(10000, 2);return 0;
}

从使用方式来说,函数对象和 lambda 表达式一样。函数对象以 rate 作为其成员变量,在定义对象时给出初始值即可,lambda 表达式通过捕获列表可以直接对该变量进行捕获。

在这里插入图片描述

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

lambda 表达式的优势有:

  • 使代码更加简洁,易读和易于维护。
  • 可以捕获外部变量,使得 lambda 表达式更加灵活。
  • 可以作为函数对象传递,使得函数式编程更加方便。

相关文章:

lambda表达式 - c++11

文章目录&#xff1a; lambda表达式概念lambda表达式语法函数对象与lambda表达式 lambda表达式概念 lambda 表达式是 c11 中引入的一种匿名函数&#xff0c;它可以在需要函数对象的地方使用&#xff0c;可以用作函数参数或返回值。lambda 表达式可以看作是一种局部定义的函数对…...

509. 斐波那契数

斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;其中 n > 1给定 n &a…...

四、[mysql]索引优化-1

目录 前言一、场景举例1.联合索引第一个字段用范围查询不走索引(分情况&#xff09;2.强制走指定索引3.覆盖索引优化4.in和or在表数据量比较大的情况会走索引&#xff0c;在表记录不多的情况下会选择全表扫描5.like 后% 一般情况都会走索引(索引下推) 二、Mysql如何选择合适的索…...

PyTorch入门学习(九):神经网络-最大池化使用

目录 一、数据准备 二、创建神经网络模型 三、可视化最大池化效果 一、数据准备 首先&#xff0c;需要准备一个数据集来演示最大池化层的应用。在本例中&#xff0c;使用了CIFAR-10数据集&#xff0c;这是一个包含10个不同类别图像的数据集&#xff0c;用于分类任务。我们使…...

0基础学习PyFlink——用户自定义函数之UDF

大纲 标量函数入参并非表中一行&#xff08;Row&#xff09;入参是表中一行&#xff08;Row&#xff09;alias PyFlink中关于用户定义方法有&#xff1a; UDF&#xff1a;用户自定义函数。UDTF&#xff1a;用户自定义表值函数。UDAF&#xff1a;用户自定义聚合函数。UDTAF&…...

英语小作文模板(06求助+描述;07描述+建议)

06 求助描述&#xff1a; 题目背景及要求 第一段 第二段 第三段 翻译成中文 07 描述&#xff0b;建议&#xff1a; 题目背景及要求 第一段 第二段...

为什么感觉假期有时候比上班还累?

假期比上班还累的感觉可能由以下几个原因造成&#xff1a; 计划过度&#xff1a;在假期里&#xff0c;人们往往会制定各种计划&#xff0c;如旅游、聚会、休息等&#xff0c;以充分利用这段时间。然而&#xff0c;如果这些计划过于紧张或安排得过于紧密&#xff0c;就会导致身…...

推理还是背诵?通过反事实任务探索语言模型的能力和局限性

推理还是背诵&#xff1f;通过反事实任务探索语言模型的能力和局限性 摘要1 引言2 反事实任务2.1 反事实理解检测 3 任务3.1 算术3.2 编程3.3 基本的句法推理3.4 带有一阶逻辑的自然语言推理3.5 空间推理3.6 绘图3.7 音乐3.8 国际象棋 4 结果5 分析5.1 反事实条件的“普遍性”5…...

《利息理论》指导 TCP 拥塞控制

欧文费雪《利息原理》第 10 章&#xff0c;第 11 章对利息的几何说明是普适的&#xff0c;任何一个负反馈系统都能引申出新结论。给出原书图示&#xff0c;本文依据于此&#xff0c;详情参考原书&#xff1a; 将 burst 看作借贷是合理的&#xff0c;它包含成本(报文)&#xf…...

Bsdiff,Bspatch 的差分增量升级(基于Win和Linux)

目录 背景 内容 准备工作 在windows平台上 在linux平台上 正式工作 生成差分文件思路 作用差分文件思路 在保持相同目录结构进行差分增量升级 服务端(生成差分文件) 客户端(作用差分文件) 背景 像常见的Android 的linux平台&#xff0c;游戏&#xff0c;系统更新都…...

【3妹教我学历史-秦朝史】2 秦穆公-韩原之战

插&#xff1a; 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家一起学习鸭~~~ 3妹&#xff1a;2哥&#xff0c;今天下班这么早&#…...

车载控制器

文章目录 车载控制器电动汽车上都有什么ECU 车载控制器 智能汽车上的控制器数量因车型和制造商而异。一般来说&#xff0c;现代汽车可能有50到100个电子控制单元&#xff08;ECU&#xff09;或控制器。这些控制器负责管理各种系统&#xff0c;如发动机管理、刹车、转向、空调、…...

回归预测 | Matlab实现RIME-CNN-SVM霜冰优化算法优化卷积神经网络-支持向量机的多变量回归预测

回归预测 | Matlab实现RIME-CNN-SVM霜冰优化算法优化卷积神经网络-支持向量机的多变量回归预测 目录 回归预测 | Matlab实现RIME-CNN-SVM霜冰优化算法优化卷积神经网络-支持向量机的多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.RIME-CNN-SVM霜冰优化算…...

使用Jaeger进行分布式跟踪:学习如何在服务网格中使用Jaeger来监控和分析请求的跟踪信息

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

添加多个单元对象

开发环境&#xff1a; Windows 11 家庭中文版Microsoft Visual Studio Community 2019VTK-9.3.0.rc0vtk-example参考代码 demo解决问题&#xff1a;不同阶段添加多个单元对象。 定义一个点集和一个单元集合&#xff0c;单元的类型可以是点、三角形、矩形、多边形等基本图形。只…...

十八、模型构建器(ModelBuilder)快速提取城市建成区——批量掩膜提取夜光数据、夜光数据转面、面数据融合、要素转Excel(基于参考比较法)

一、前言 前文实现批量投影栅格、转为整型,接下来重点实现批量提取夜光数据,夜光数据转面、夜光数据面数据融合、要素转Excel。将相关结果转为Excel,接下来就是在Excel中进行阈值的确定,阈值确定无法通过批量操作,除非采用其他方式,但是那样的学习成本较高,对于参考比较…...

HarmonyOS开发:基于http开源一个网络请求库

前言 网络封装的目的&#xff0c;在于简洁&#xff0c;使用起来更加的方便&#xff0c;也易于我们进行相关动作的设置&#xff0c;如果&#xff0c;我们不封装&#xff0c;那么每次请求&#xff0c;就会重复大量的代码逻辑&#xff0c;如下代码&#xff0c;是官方给出的案例&am…...

【杂记】Ubuntu20.04装系统,安装CUDA等

装20.04系统 安装系统的过程中&#xff0c;ROG的B660G主板&#xff0c;即使不关掉Secure boot也是可以的&#xff0c;不会影响正常安装&#xff0c;我这边出现问题的主要原因是使用了Ventoy制作的系统安装盘&#xff0c;导致每次一选择使用U盘的UEFI启动&#xff0c;就会跳回到…...

040-第三代软件开发-全新波形抓取算法

第三代软件开发-全新波形抓取算法 文章目录 第三代软件开发-全新波形抓取算法项目介绍全新波形抓取算法代码小解 关键字&#xff1a; Qt、 Qml、 抓波、 截获、 波形 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#xff08;Qt Meta-Object …...

分享一个基于asp.net的供销社农产品商品销售系统的设计与实现(源码调试 lw开题报告ppt)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人七年开发经验&#xff0c;擅长Java、Python、PHP、.NET、微信小程序、爬虫、大数据等&#xff0c;大家有这一块的问题可以一起交流&#xff01; &#x1f495;&…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…...

【Oracle】分区表

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散

前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说&#xff0c;在叠衣服的过程中&#xff0c;我会带着团队对比各种模型、方法、策略&#xff0c;毕竟针对各个场景始终寻找更优的解决方案&#xff0c;是我个人和我司「七月在线」的职责之一 且个人认为&#xff0c…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...