菜鸟教程链接:
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;
};
- 对于2中我们由于没有指定返回值。因为这个Lambda函数的返回值类型可以通过自动类型推断推导出来,因此可以省略掉显式的返回类型。
2.如果不想使用 auto,可以显式指定变量的类型。在这个Lambda函数中,可以将 auto 替换为显式的类型 std::function<vector
以下是使用显式类型说明的代码示例:
std::function<vector<int>(int)> bfs = [&](int s) -> vector<int> {
// ...
};
在这个示例中,我们将 bfs 的类型指定为 std::function<vector
需要注意的是,在Lambda函数的定义后面加上 -> vector
使用显式类型说明可以提高代码的可读性,因为读者可以直接看到变量的具体类型。但对于较长或复杂的类型名称,显式说明可能会增加代码的冗余程度。因此,使用 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