搜尋

首頁  >  問答  >  主體

c++ - lambda 递归为何会crash

下面这段代码运行会crash

#include <iostream>
#include <windows.h>
int main() {
        std::function<void()> fun = [=]{
                std::cout << "AAA" << std::endl;
                Sleep(1000);
                fun();
        };
        fun();
        return 0;
}

复制代码
把[=]改成[&] 就能通过了

#include <iostream>
#include <windows.h>
int main() {
        std::function<void()> fun = [&]{
                std::cout << "AAA" << std::endl;
                Sleep(1000);
                fun();
        };
        fun();
        return 0;
}

复制代码
而我的函数需要用[=]方式,为啥会crash呢

巴扎黑巴扎黑2807 天前727

全部回覆(2)我來回復

  • ringa_lee

    ringa_lee2017-04-17 12:59:58

    fun要先構造再調用,但是由於是值拷貝,所以在fun構造的時候拷貝的那個fun就可能是不完整的。

    warning: variable 'fun' is uninitialized when used within its own initialization [-Wuninitialized]
                    fun();
                    ^~~

    如果一定要連fun也拷貝(以數值捕捉),可以採用delay的方式:

    #include <iostream>
    #include <windows.h>
    int main() {
            std::function<void()> fun = [=, &fun]{
                    std::function<void()> delayFun = [&]{
                            std::function<void()> funCopy = fun;
                            funCopy();
                    };
                    std::cout << "AAA" << std::endl;
                    Sleep(1000);
                    delayFun();
            };
            fun();
            return 0;
    }

    這樣既無warning,程式行為也符合預期。

    回覆
    0
  • 大家讲道理

    大家讲道理2017-04-17 12:59:58

    第一段程式碼,你是用拷貝的方式實作fun()函數的,也就是每次fun()被呼叫的時候就會同時拷貝一份,然後拷貝裡面又會拷貝,這樣重複若干次以後就會有很多個fun()在同時遞歸,這是一個幾何成長的過程。這有點像linux中的fork函數,如果把fork寫在循環裡,那fork出來的進程也是一個幾何增長的過程。但是這個複製+遞歸的過程還是比較複雜的,難以用一句話解釋清楚。有興趣的話可以去搜尋fork相關的文章,對你理解這個問題會有幫助

    第二段程式碼不會拷貝出新的函數,所以只有一個fun()在遞歸,這是一個線性增長的過程(但是在遞歸達到極限時仍然會crash的,只是需要的時間很長,因為你2次遞歸之間會間隔1秒鐘。

    回覆
    0
  • 取消回覆