簡體   English   中英

為什么我不能在C ++中捕獲遞歸lambda函數?

[英]Why can't I capture a recursive lambda function in C++?

我發現,如果lambda是調用自身的遞歸函數,則不能像在C ++中的閉包中那樣被另一個lambda捕獲。

我有一些這樣的代碼:

#include <memory>
#include <functional>
#include <iostream>

class ClassA
{
public:
    std::function<void()> FuncA;
    void Call()
    {
        FuncA();
    }
};

class ClassB
{
    std::unique_ptr<ClassA> pA = std::make_unique<ClassA>();
public:
    void Setup()
    {
        std::function<void(int)> FuncB = [&](int a)
        {
            std::cout << "a = " << a << std::endl;
            if(a > 0)
                FuncB(a-1);
        };

        pA->FuncA = [&]()
        {
            FuncB(10.0f);
        };
    }
    void Run()
    {
        Setup();
        pA->Call();
    }   
};

int main() {

    ClassB B;
    B.Run();
}

調用FuncA時會發生異常,因為其中的FuncB將為空指針。

我的問題是為什么我不能捕獲遞歸lambda函數?

我正在使用Visual Studio 2015

編輯:如果通過復制在FuncA中捕獲FuncB,則如果FuncB不是遞歸的,則可以使用。 像這樣:

class ClassB
{
    std::unique_ptr<ClassA> pA = std::make_unique<ClassA>();
public:
    void Setup()
    {
        std::function<void(int)> FuncB = [FuncB](int a)
        {
            std::cout << "a = " << a << std::endl;
            if (a > 0)
                FuncB(a - 1);
        };

        pA->FuncA = [FuncB]()
        {
            FuncB(10.0f);
        };
    }
    void Run()
    {
        Setup();
        pA->Call();
    }
};

您正在通過引用捕獲FuncB ,但是在Setup返回時FuncB被破壞,留下了懸掛的引用。

如果將FuncB更改為按值捕獲,則第一個lambda會在對其進行初始化之前捕獲它,這將導致未定義的行為。

我想不出任何辦法來獲取lambda來捕獲自己,就像您嘗試做的那樣。

對您的代碼進行少量修改,可以正常工作:

#include <iostream>
#include <functional>

struct A
{
    std::function<void()> fa;
    void call() { fa(); }
};

struct B
{
    A *pA;
    B() {pA=nullptr; }
    typedef std::function<void(int)> FB;
    FB fb;
    void Setup()
    {
        fb=[&](int i)
        {
            std::cout << "i = " << i << "\n";
            if(i > 0) fb(i-1);
        };
        if (pA) { pA->fa=[&]() { fb(10.0f); }; }
    }
    void Run(A*p)
    {
        pA=p;
        Setup();
        pA->call();
    }
};

int main()
{
    A a;
    B b;
    b.Run(&a);
    return 0;
}

也許這將幫助您完善算法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM