Lambda 函数(也叫 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 类型参数并返回 vector 类型结果的函数。

具体来说,std::function 是 C++ 标准库中的一个模板类,用于封装函数、函数指针、函数对象等可调用实体。它提供了一种通用的方式来定义和使用不同类型的可调用对象,使得它们可以被像函数一样进行调用和操作。

在这个特定的例子中,std::function<vector(int)> 表示一个能接受 int 类型参数并返回 vector 类型结果的函数对象。也就是说,这个函数对象可以被当作一个函数来调用,并且输入一个 int 参数后会返回一个 vector 类型的值。

使用 std::function 可以方便地将Lambda函数、普通函数、函数对象等封装成一个统一的类型,从而使其更加灵活和通用。通过声明一个 std::function 对象,我们可以存储、传递和调用各种类型的可调用实体,而不需要关心具体的类型信息。这在实现回调机制、事件处理等场景下非常有用。

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

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功能。


__EOF__

本文作者爱飞鱼
本文链接https://www.cnblogs.com/mathiter/p/17738333.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   potential-star  阅读(233)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示