lambda实现递归
在 C++ 中,lambda 表达式在定义时实际上不能直接调用自己,因为 lambda 在定义时没有名字。要让一个 lambda 自我引用,你需要使用一个技巧:将 lambda 自身作为参数传递给自己,从而实现递归。
为什么 Lambda 自身在定义时无法被调用?
- 匿名性:Lambda 表达式是匿名的,编译器在定义时不为其生成名称,因此无法在其内部直接引用或调用自己。
- 捕获和名称:在 lambda 定义时,虽然可以捕获外部变量,但不能直接引用自身,因为 lambda 的名字在定义时尚未确定。
解决方案:使用引用捕获
通过使用 lambda 的引用捕获(通常是将 lambda 自身作为参数传递),你可以在 lambda 内部实现递归。假设我们要查找一个 AActor
下所有的 URectLightComponent
,我们可以使用一个 lambda 函数来递归地遍历所有子组件。
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Components/RectLightComponent.h"
#include "GameFramework/Actor.h"
class FRectLightFinder
{
public:
static void FindRectLightComponents(AActor* Actor, TArray<URectLightComponent*>& OutRectLightComponents)
{
if (!Actor)
{
return;
}
// 定义 lambda 函数进行递归
auto RecursiveSearch = [](USceneComponent* Component, TArray<URectLightComponent*>& OutComponents, auto& RecursiveSearchRef)
{
if (!Component)
{
return;
}
// 检查是否是 RectLightComponent
if (URectLightComponent* RectLightComponent = Cast<URectLightComponent>(Component))
{
OutComponents.Add(RectLightComponent);
}
// 递归查找所有子组件
for (USceneComponent* Child : Component->GetChildrenComponents(true))
{
RecursiveSearchRef(Child, OutComponents, RecursiveSearchRef);
}
};
// 从 Actor 的根组件开始递归
RecursiveSearch(Actor->GetRootComponent(), OutRectLightComponents, RecursiveSearch);
}
};
解释
- Lambda 函数:
RecursiveSearch
是一个递归的 lambda 表达式,它负责遍历组件及其子组件。注意,lambda 使用auto& RecursiveSearchRef
参数来递归调用自己。为了在 lambda 内部递归调用自身,必须通过引用捕获。 RecursiveSearchRef
:这参数用于实现递归调用,因为 lambda 自身在定义时还无法被调用。我们将它作为参数传递给 lambda,并在递归时引用它。- 递归逻辑:在
RecursiveSearch
内部,我们首先检查当前组件是否是URectLightComponent
。如果是,我们将其添加到结果数组中。然后我们递归地遍历当前组件的所有子组件。 - 启动递归:在
FindRectLightComponents
函数中,我们从Actor
的根组件开始调用递归 lambda。
关键点
auto& RecursiveSearchRef
:在 lambda 的参数列表中,使用auto& RecursiveSearchRef
来传递 lambda 自身的引用。这允许 lambda 在其内部递归调用自身。- 递归调用:通过
RecursiveSearchRef
引用,lambda 可以递归调用自己,实现遍历所有子组件的功能。
这种方式有效地绕过了 lambda 定义时无法直接自引用的问题,允许你在 lambda 内部实现递归逻辑。
标签:调用,递归,实现,Actor,RecursiveSearchRef,组件,lambda From: https://www.cnblogs.com/Dreammoon/p/18388117