首页 > 其他分享 > Lambda 函数(也叫 Lambda 表达式)。

Lambda 函数(也叫 Lambda 表达式)。

时间:2023-09-30 22:34:14浏览次数:35  
标签:函数 auto 显式 类型 dis 表达式 Lambda

菜鸟教程链接:
https://www.runoob.com/cplusplus/cpp-functions.html

C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。

Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量作为参数传递,还可以像函数一样对其求值。

Lambda 表达式本质上与函数声明非常类似。Lambda 表达式具体形式如下:

[capture](parameters)->return-type{body}
/*1.[]是负责捕获哪些外部对象,并且可以决定是值传递还是地址快递.
2.()里是传递的参数。在C++14标准中引入了泛型Lambda的概念,允许在Lambda表达式的形参列表中使用auto关键字作为模板参数。
3.->对于返回值。如果常规来说是void的话是可以省略的,用了auto推断也可以省略,但如果是递归调用且参数里用了auto去推断self的话会编译错误。
*/

下面举两个实战例子来说进一步说明使用的细节

1.在这段代码中,lambda 函数 dfs 接受两个参数 self 和 x。其中 self 是一个自引用的函数对象,用于在递归调用中调用自身。x 表示当前正在访问的节点。

通过使用 self 自引用函数对象,在递归调用中可以继续调用 dfs 函数,实现深度优先搜索的遍历过程。这种技巧通常用于解决需要递归调用的问题,其中 lambda 函数可以作为一个包装器来保存和传递自身引用。

使用自引用 lambda 函数不仅可以简化代码结构,还可以避免必须将递归函数定义为独立的外部函数,从而提高代码的可读性。

auto dfs=[&](auto self,int x)->void{
		
		
		vis[x]=true;
		for(auto y:adj[x]){
			if(!vis[y]){
				par[y]=x;
				dep[y]=dep[x]+1;
				self(self,y);
			}
			else if(dep[y]<dep[x]-1){
				for(int i=x;;i=par[i]){
					if(u==-1||dis[u]>dis[i]){
						u=i;
					}
				if(i==y)break;
			}
		}
		}
	};

代码中的->void不能省略,不然会导致 lambda 函数自身引用参数的类型无法推断

2.这个Lambda函数使用的捕获列表 [&] 表示采用引用方式捕获外部作用域中的所有变量。Lambda函数接受一个整数参数 s,表示BFS算法的起点。在函数内部,定义了一个长度为 n 的距离数组 dis,并初始化为-1,表示所有节点都不可达。然后,将起点的距离设为0,将起点加入队列。

接下来是BFS算法的主循环。从队列中取出首个节点 x,然后遍历节点 x 的邻居节点 y。如果节点 y 未被访问过(其距离为-1),则更新其距离值为当前节点 x 的距离加1,并将其加入队列。这样就实现了广度优先搜索的扩展步骤。

最后,返回计算得到的距离数组 dis,它记录了起点 s 到每个节点的最短路径长度。

通过使用Lambda函数,可以方便地将BFS算法封装为一个可复用的功能单元,而无需显式定义一个独立的函数。这种方式使得代码更加简洁和可读性更高。

	auto bfs=[&](int s){
		vector<int>dis(n,-1);
		dis[s]=0;
		queue<int>q;
		q.push(s);
		while(q.size()){
			int x=q.front();
			q.pop();
			for(auto y:adj[x]){
				if(dis[y]==-1){
					dis[y]=dis[x]+1;
					q.push(y);
				}
			}
		}
		return dis;
	};
  1. 对于2中我们由于没有指定返回值。因为这个Lambda函数的返回值类型可以通过自动类型推断推导出来,因此可以省略掉显式的返回类型。

2.如果不想使用 auto,可以显式指定变量的类型。在这个Lambda函数中,可以将 auto 替换为显式的类型 std::function<vector(int)>。

以下是使用显式类型说明的代码示例:

std::function<vector<int>(int)> bfs = [&](int s) -> vector<int> {
    // ...
};

在这个示例中,我们将 bfs 的类型指定为 std::function<vector(int)>,表示它是一个接受整数参数并返回 vector 类型结果的函数对象。

需要注意的是,在Lambda函数的定义后面加上 -> vector 来显式指定返回类型,这是因为Lambda函数的返回类型无法自动推断,需要显式声明。

使用显式类型说明可以提高代码的可读性,因为读者可以直接看到变量的具体类型。但对于较长或复杂的类型名称,显式说明可能会增加代码的冗余程度。因此,使用 auto 进行类型推断是一种常见的做法,可以使代码更简洁和易于理解。

1和2两个例子中我们都使用了泛型lambda

在C++14标准中引入了泛型Lambda的概念,允许在Lambda表达式的形参列表中使用auto关键字作为模板参数。

下面是一个使用泛型Lambda的例子:
auto print = [](auto value) {
    std::cout << value << std::endl;
};

print(10);        // 以int类型打印
print(3.14);      // 以double类型打印
print("Hello");   // 以const char*类型打印

在上述代码中,Lambda表达式print接受一个参数value,并使用auto关键字进行了模板类型推断。这使得我们可以将不同类型的值传递给print函数,并通过std::cout打印出来。

泛型Lambda提供了更灵活的操作,因为它可以处理多种不同类型的输入,而无需为每种类型编写不同的Lambda函数。

需要注意的是,泛型Lambda在C++14及以后的标准中才支持,如果你的编译器不支持C++14及以上的标准,可能无法使用泛型Lambda功能。

标签:函数,auto,显式,类型,dis,表达式,Lambda
From: https://www.cnblogs.com/mathiter/p/17738333.html

相关文章

  • golang 代码实现一个工具函数:用于合并两个go map
    内容来自对chatgpt的咨询初始化一个新map,然后遍历两个旧map,把每个元素都存到新map即可。packagemainimport"fmt"//MergeMaps创建一个新的map用于保存合并后的值。返回新的map。funcMergeMaps(destMap,sourceMapmap[string]interface{})map[string]inter......
  • 无涯教程-JavaScript - T函数
    描述T函数返回值所引用的文本。语法T(value)争论Argument描述Required/OptionalValueThevalueyouwanttotest.RequiredNotes如果value是或引用文本,则T返回值。如果值不引用文本,则T返回""(空文本)。通常不需要在公式中使用T函数,因为MicrosoftExcel会根......
  • 拟合不同的冷却方式(分类变量)下,物料温度加入两个分类变量, 物料类型和冷却方式, 给
    在机器学习中,拟合不同冷却方式下物料温度随时间下降的规律可以使用不同的算法和方法。以下是四种常见的方法,它们可以用来生成数据集、拟合模型、解释参数和输出函数方程,以及解释它们的实际意义。线性回归:方法:线性回归是一种用于拟合线性关系的方法,通过寻找最佳拟合直线来预测温度随......
  • 无涯教程-JavaScript - SUBSTITUTE函数
    描述在文本字符串中用new_text替换old_text。语法SUBSTITUTE(text,old_text,new_text,[instance_num])争论Argument描述Required/OptionalTextThetextorthereferencetoacellcontainingtextforwhichyouwanttosubstitutecharacters.RequiredOld_t......
  • 无涯教程-JavaScript - RIGHT函数
    描述RIGHT函数根据您指定的字符数返回文本字符串中的最后一个或多个字符。RIGHTB根据您指定的字节数返回文本字符串中的最后一个或多个字符。RIGHT适用于使用单字节字符集(SBCS)的语言,而RIGHTB适用于使用双字节字符集(DBCS)的语言。您计算机上的默认语言设置会影响返回值,如......
  • 使用正则表达式判断日期字符串格式是否合法遇到的问题(解决)
    引言我们在使用SpringMVC从前端接受传递过来的日期数据时,默认传递过来的数据是String类型,如果我们从前端传递过来的数据格式是yyyy/MM/dd,SpringMVC有内置类型转化器会将String类型自动转化成Date类型。但如果我们从前端传递过来的数据格式是yyyy-MM-dd,SpringMVC的内置转化器就不......
  • C++ 转换构造函数
    在C++中如果一个构造函数只有一个参数,那么这个构造函数就是转换构造函数(ConvertingConstructor),这个构造函数可以将参数类型转换成构造函数所在的类对应的类型。举个例子,假设有如下类Complex:1classComplex{2private:3inti;4intj;56public:......
  • 可变参数函数原理
    可变参数列表我们想通过一个例子来引出我们这个话题.如果我们想要求两个数的最大值,这个函数是非常容易的.intGetMax(intx,inty){if(x>y){returnx;}returny;}intmain(){inta=10;intb=20;intmax=......
  • 简单数学函数(最小公倍数与最大公约数与快速幂)
    最大公约数(\(gcd\)):intgcd(inta,intb){returnb?gcd(b,a%b):a;}最小公倍数(\(lcm\)):intlcm(inta,intb){returna/gcd(a,b)*b;//注意:除数为gcd(a,b)}快速幂:template<typenameA,typenameB,typenameC>Cpow(Ax,By,Cp){ if(x==......
  • 实验1 C语言开发环境使用和数据类型.运算符.表达式
    task1.c代码#include<stdio.h>intmain(){printf("O\n");printf("<H>\n");printf("II\n");return0;} 运行结果  task1_2.c代码 #include<stdio.h>intmain(){printf(&quo......