lambda實現遞迴

Dream_moon發表於2024-08-30

lambda實現遞迴

在 C++ 中,lambda 表示式在定義時實際上不能直接呼叫自己,因為 lambda 在定義時沒有名字。要讓一個 lambda 自我引用,你需要使用一個技巧:將 lambda 自身作為引數傳遞給自己,從而實現遞迴。

為什麼 Lambda 自身在定義時無法被呼叫?

  1. 匿名性:Lambda 表示式是匿名的,編譯器在定義時不為其生成名稱,因此無法在其內部直接引用或呼叫自己。
  2. 捕獲和名稱:在 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);
    }
};

解釋

  1. Lambda 函式RecursiveSearch 是一個遞迴的 lambda 表示式,它負責遍歷元件及其子元件。注意,lambda 使用 auto& RecursiveSearchRef 引數來遞迴呼叫自己。為了在 lambda 內部遞迴呼叫自身,必須透過引用捕獲。
  2. RecursiveSearchRef:這引數用於實現遞迴呼叫,因為 lambda 自身在定義時還無法被呼叫。我們將它作為引數傳遞給 lambda,並在遞迴時引用它。
  3. 遞迴邏輯:在 RecursiveSearch 內部,我們首先檢查當前元件是否是 URectLightComponent。如果是,我們將其新增到結果陣列中。然後我們遞迴地遍歷當前元件的所有子元件。
  4. 啟動遞迴:在 FindRectLightComponents 函式中,我們從 Actor 的根元件開始呼叫遞迴 lambda。

關鍵點

  • auto& RecursiveSearchRef:在 lambda 的引數列表中,使用 auto& RecursiveSearchRef 來傳遞 lambda 自身的引用。這允許 lambda 在其內部遞迴呼叫自身。
  • 遞迴呼叫:透過 RecursiveSearchRef 引用,lambda 可以遞迴呼叫自己,實現遍歷所有子元件的功能。

這種方式有效地繞過了 lambda 定義時無法直接自引用的問題,允許你在 lambda 內部實現遞迴邏輯。

相關文章