C++ lambda 表达式

lambda 表达式

lambda 表达式有时也称为 lambda 函数,或者直接简称为 lambda ;它是定义和使用匿名函数对象的一种简便的方式。
一条 lambda 表达式包含以下组成要件:

  • 一个可能为空的捕获列表,指明定义环境中的哪些名字能被用在 lambda 表达式内,以及这些名字的访问方式是拷贝还是引用;捕获列表位于[]内。
  • 一个可选的参数列表,指明 lambda 表达式所需的参数;参数列表位于()内。
  • 一个可选的 mutable 修饰符,指明该 lambda 表达式可能会修改它自身的状态(即,改变通过值捕获的变量的副本)。
  • 一个可选的 noexcept 修饰符。
  • 一个可选的->形式的返回类型声明。
  • 一个表达式体,指明要执行的代码,表达式体位于{}内。

即,一个 lambda 表达式具有如下形式:

		[捕获列表](参数列表)->返回值{表达式体};

在 lambda 表达式的概念中,传参、返回结果以及定义表达式体等环节都与函数的相应概念是一致的。
区别在于,函数没有提供局部变量“捕获”的功能;这意味着 lambda 表达式可以作为局部函数使用,而普通函数不能。

lambda 的类型

lambda 表达式是一种局部类类型,它含有一个构造函数以及一个 const 成员函数 operator()()。
lambda 表达式不仅可以作函数实参,还能用于初始化一个声明为 auto 或者std::function<R(AL)>的变量。其中,R 是 lambda 的返回类型,AL是它的类型参数列表。
lambda 表达式作函数实参

	vector<int> v{ 1,3,3,7,9 };for_each( v.begin(), v.end(), [](int& x){x += 1;} ); //每个元素都加一

lambda 表达式用于初始化一个声明为 auto 的变量

	vector<int> v{ 1,3,3,7,9 };auto f = [](int& x) { x += 1; };for_each( v.begin(), v.end(),f );

如果一个 lambda 什么也不捕获,则我们可以将它赋值给一个指向正确类型函数的指针。

	int (*p)(int) = [](int a) {return a; };cout << (*p)(42) << endl; //输出 42

调用与返回

除了关于捕获的规则外,lambda 的大多数规则都是从函数和类借鉴而来。
然而,有两点需要注意:

  • 如果一个 lambda 表达式不接受任何参数,则其参数列表可被忽略。
  • lambda 表达式的返回类型能由 lambda 表达式本事推断得到。
    • 如果 lambda 的主体部分不包含 return 语句,则该 lambda 的类型是 void。
    • 如果 lambda 的主体部分只包含一个 return 语句,则该 lambda 的类型是该 return 表达式的类型。
    • 其它情况下,必须显示地提供一个返回类型。
      可以忽略参数列表和返回类型,但是必须永远包含捕获列表和函数体。
	auto f = [] {return 42; }; //lambda 最简形式:[]{表达式体};

lambda 表达式的调用方式与普通函数调用的方式相同。

	auto max = [](int x, int y) { return x > y ? x : y; };cout << max(10,30) << endl; //输出 30

当需要为一个 lambda 表达式定义返回类型时,必须使用尾置返回类型。

	auto max = [](int x, double y) ->int{if (x > y)return x;else if (x < y)return y;elsereturn 0;};cout << max(10, 30) << endl;  //输出 30

捕获

值捕获

通过在捕获列表中列出局部变量的名字,就可以在 lambda 表达式中访问它们了。
与函数传递参数类似,通过值捕获传递的是局部变量的副本;不同的是,被捕获的变量的值是在 lambda 表达式创建时拷贝,而不是在调用时拷贝。

void fun(void)
{int x =10, y = 20;     //局部变量auto max = [x,y](){ return x > y ? x : y; }; x = 30; // 对 x 的修改,不会改变 max() 返回的结果cout << max() << endl; //输出 20
}

默认情况下,对于一个通过值捕获的变量的副本, lambda 不会改变其值。
如果希望能改变一个通过值捕获的变量的副本,就必须在参数列表后面加上关键字 mutable。

void fun(void)
{int x = 1, y = 2; //局部变量auto f = [x, y]() mutable { x += 10; y += 10; 	cout << x << ',' << y << endl; };cout << x << ',' << y << endl; //调用前,x = 1,y = 2f();                           //调用中,x = 11,y = 12cout << x << ',' << y << endl; //调用后,x = 1,y = 2
}

引用捕获

只有通过引用的捕获才允许修改调用环境中的变量。

void fun(void)
{int x = 1, y = 2; //局部变量auto f = [&x, &y]() { x += 10; y += 10; };cout << x << ',' << y << endl; //调用前,x = 1,y = 2f();cout << x << ',' << y << endl; //调用后,x = 11,y = 12
}

lambda 引入符[]的形式有很多种:

  • []空捕获列表。即,在 lambda 表达式内部无法使用其外层上下文中的任何局部名字。
  • [&]通过引用隐式捕获。所有局部名字都能使用,所有局部变量都通过引用访问。
  • [=]通过值隐式捕获。所有局部名字都能使用,所有局部名字都指向局部变量的副本。
  • [捕获列表]显示捕获。以&为前缀的局部名字通过引用捕获,其它变量通过值捕获;捕获列表中,可以出现this
  • [&,捕获列表]对于名字没有出现在捕获列表中的局部变量,通过引用隐式捕获;捕获列表中,可以出现this;列出的名字不能以&为前缀;捕获列表中的变量名通过值的方式捕获。
  • [=,捕获列表]对于名字没有出现在捕获列表中的局部变量,通过值隐式捕获;捕获列表中,不允许包含this;列出的名字必须以&为前缀;捕获列表中的变量名通过引用的方式捕获。

在捕获列表中,以&为前缀的局部名字总是通过引用捕获;相反地,不以&为前缀的局部名字总是通过值捕获。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/228653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

70.爬楼梯

题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a; 给定 n 是一个正整数。 示例 1: 输入&#xff1a; 2 输出&#xff1a; 2 解释&#xff1a; 有两种方法可以爬到楼顶…

Python之初识类与对象

类的概念与定义 在生活中&#xff0c;我们走在路边&#xff0c;看到一辆车&#xff0c;大脑中首先想到的是“这是一辆车&#xff0c;然后才是这是一辆什么牌子的车”&#xff0c;在这里&#xff0c;我们就用到了编程中的类的概念。同样的&#xff0c;看到一条小狗&#xff0c;…

React-Hooks

一、类组件和函数式组件的对比 Hook 的特性&#xff1a;在编写class 的情况下&#xff0c;使用state 以及其他React 特性&#xff08;比如生命周期&#xff09; 类组件相比于函数式组件的优势&#xff1a; 类组件可以定义自己的state&#xff0c;用来保存组件自己内部的状态…

Linux:进程地址空间

目录 1.程序地址空间 2.进程地址空间 1.程序地址空间 我们在讲C/C语言的时候&#xff0c;32位平台下&#xff0c;我们见过这样的空间布局图 我们来验证一下这张图的正确性&#xff1a; int un_gval;int init_gval100;int main(int argc, char* argv[],char* env[]){//代码…

网络安全事件分级指南

文章目录 一、特别重大网络安全事件符合下列情形之一的&#xff0c;为特别重大网络安全事件&#xff1a;通常情况下&#xff0c;满足下列条件之一的&#xff0c;可判别为特别重大网络安全事件&#xff1a; 二、重大网络安全事件符合下列情形之一且未达到特别重大网络安全事件的…

Shell脚本 变量 语句 表达式

常见的解释器 #!/bin/sh #不推荐(了解) #!/bin/bash #!/usr/bin/python #!/bin/awk#!后跟的字符表示要启动的程序&#xff0c;该程序读取该文件执行。 #! 是一个约定的标记&#xff0c;它告诉系统这个脚本需要什么解释器来执行shell 函数 myShellName () {command1 }函数调用…

Linux: network: tcpdump:通过分析应该抓到包了,却没找不到的另一个原因:-s

最近又遇到一个类似的问题,也是在tcpdump抓到的包里没有找到应该看到的包,搞得很迷惑。这次是现场技术给研发挖了一个坑,给带偏了。研发自己抓包,发现根本就是没有丢在主机和虚拟机之间,也不是Linux内核丢掉了包。 那怎么回事呢?如果研发从主机上抓的没有问题,而是技术…

【计算机设计大赛作品】VR项目-中国古字贾湖刻字—信息可视化赛道获奖项目深入剖析【可视化项目案例-21】

🎉🎊🎉 你的技术旅程将在这里启航! 记得看本专栏里顶置的可视化宝典导航贴哦! 🚀🚀 本专栏为可视化专栏,包含现有的所有可视化技术。订阅专栏用户在文章底部可下载对应案例完整源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不论你…

前端实现一个时间区间内,再次单选功能,使用Antd组件库内日历组件Calendar

需求&#xff1a;需要先让用户选择一个时间区间&#xff0c;然后再这个时间区间中&#xff0c;让用户再次去单选其种特殊日期。 思路&#xff1a; 1.先用Antd组件库中日期选择DatePicker.RangePicker实现让用户选择时间区间 2.在选择完时间区间后&#xff0c;用这个时间区间…

从零开始 --- 创建vue项目

1、Vue脚手架创建项目 vue create home_vue 我选择了vue3 2、引入element-plus npm i element-plus vue2 对应 npm i element-ui main.js中 import { createApp } from vue import App from ./App.vue import ElementPlus from element-plus import element-plus/theme-…

英语中疑问句

一般疑问句 Is there any tea in the cup? Do you have any children? May I have some fish? Would you like some tea? Could you give me some advices? Shall we buy some vegetables? Should you do like this? Can I borrow some money from you? Why not have …

Spring框架知识总结

目录 1、Spring框架有哪些设计模式&#xff1f; 2、介绍一下Spring框架和SpringBoot框架&#xff1f; 3、介绍一下SpringBoot具有哪些功能模块&#xff1f; 4、Spring用到了什么组件&#xff1f; 5、什么是IoC? 什么是AOP&#xff1f; 6、SpringBoot运行原理&#xff1…

鸿蒙HarmonyOS开发用什么语言

1.网上流行一句有中国底蕴的话&#xff1a;鸿蒙系统方舟框架盘古大模型。都方舟框架了肯定主推的是ArkUI框架。其实还能使用C、Java和Js开发。 2.从API8开始&#xff0c;Java语言已经从鸿蒙开发剔除了&#xff0c;而官方推荐的是ArkTs.下图是ArkTS与TS、JS的关系。 ArkTs 是TS的…

BFS:八数码问题求解

八数码原题 剖析一下BFS BFS算法是一种图遍历算法&#xff0c;它从起点开始&#xff0c;逐层扩展搜索范围&#xff0c;直到找到目标节点为止。 BFS算法一般选择队列作为节点存储的数据结构&#xff0c;我们将搜索目标节点的问题抽象为寻找目标状态&#xff0c;那么队列…

Vue3 reative回显问题

1. reactive 在做项目的时候通常会遇到这种情况&#xff0c;比如我们有一个 Table 显示数据&#xff0c;添加 Table 数据的时候使用 dialog 弹出&#xff0c;在里面填写字段然后添加。 在 vue3 中&#xff0c;对于对象的响应式定义推荐使用 reactive &#xff0c;那么可以写入…

运筹学经典问题(二):最短路问题

问题描述 给定一个图&#xff08;有向图或无向图&#xff09; G ( V , E ) G (V, E) G(V,E)&#xff0c; V V V是图中点的集合&#xff0c; E E E是图中边的集合&#xff0c;图中每条边 ( i , j ) ∈ E (i, j) \in E (i,j)∈E都对应一个权重 c i j c_{ij} cij​&#xff08;…

Android取消深色适配

从Android10&#xff08;API 29&#xff09;开始&#xff0c;在原有的主题适配的基础上&#xff0c;Google开始提供了Force Dark机制&#xff0c;在系统底层直接对颜色和图片进行转换处理&#xff0c;原生支持深色模式。当系统设置深色主题背景或者进入省电模式情况下会进入深色…

2023年烟花爆竹经营单位主要负责人证模拟考试题库及烟花爆竹经营单位主要负责人理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年烟花爆竹经营单位主要负责人证模拟考试题库及烟花爆竹经营单位主要负责人理论考试试题是由安全生产模拟考试一点通提供&#xff0c;烟花爆竹经营单位主要负责人证模拟考试题库是根据烟花爆竹经营单位主要负责人…

C++ STL容器概览

容器概览 容器分类 顺序容器提供对元素&#xff08;半开&#xff09;序列的访问。 vectorlistforward_listdeque 关联容器提供基于关键字的关联查询。 有序关联容器&#xff1a;通常用平衡二叉树&#xff08;红黑树&#xff09;实现。 mapmultimapsetmultiset 无序关联容器&a…

NestJS使用gRPC实现微服务通信

代码仓库地址&#xff1a;https://github.com/zeng-jc/rpc-grpc-practice 1.1 基本概念 gRPC 基于 Protocol Buffers&#xff08;protobuf&#xff09;作为接口定义语言&#xff08;IDL&#xff09;&#xff0c;意味着你可以使用 protobuf 来定义你的服务接口&#xff0c;gRP…