2016-07-28 47 views
1

I've recently learned,我可以這樣做:衰減的lambda指向哪個函數存儲?它是如何釋放的?

並理解,自由捕獲拉姆達衰變到一個函數指針,as confirmed by GCC

bool (*)()

但存儲實際的函數對象在哪裏? 它是如何釋放的?爲什麼我可以存儲一個指向臨時lambda的指針?我理解常量引用延長對象生命期的語言的角落案例,所以我期望lambda衰減到某種類型,而不是原始指針。

+0

如果您有興趣,可以參考[Clang的源代碼](https://github.com/llvm-mirror/clang/blob/master/lib/Sema/SemaLambda.cpp#L1147)。 – chris

+4

當你編寫'bool foo(){return true;}',然後寫'auto a = &foo;''foo'如何釋放?答:不是。 – immibis

+0

@immibis這是啓發 – Kahler

回答

4

lambda不是一個指針,但可以轉換爲指向函數的指針。

函數不會像C++中的值那樣「存儲」。實際上,它們存在於可執行文件的代碼段中,並由可執行文件/ dll加載程序加載到寫保護的執行位集頁面中。

無狀態lambda的代碼沒有什麼不同。轉換隻是返回一個指向函數的指針,其效果與lambda的主體相同,不多也不少。

請記住,這隻適用於無狀態lambda。沒有非靜態數據要存儲。現在

,該+事情是有點一招,因爲當你申請一元operator+一個對象,轉換嘗試,和一個uniqie類型(函數對象函數指針轉換)被發現。

我猜具體代碼可能會有所幫助。

struct fake_lambda { 
    static void action(){ std::cout<<"hello?\n"; } 
    void operator()()const{action();} 
    using ptr=void(*)(); 
    operator ptr()const{return &fake_lambda::action;} 
}; 

現在auto f=+fake_lambda{};是一個指向打印"hello?\n"功能。

這與auto f=+[](){std::cout<<"hello\n";};基本相同,但更詳細。

+0

靜態/未保存的部分會讓我有點困惑......如果代碼保存在一個單獨的區域,這是否意味着我可以安全地[返回一個衰減的指針到本地lambda](http://coliru.stacked-crooked .COM/A/fc9d87a68f5c4795)? – Kahler

+0

...或者是您提到的受保護段本地和展開就像本地變量時函數返回? – Kahler

+2

@kahler C++沒有概念或可能性,指向實際函數的函數指針不再有效。 (它可以是未初始化的,或者是空的,或者是被賦值的,但是一個有效的函數指針和它的拷貝不會變得無效)。現實中動態鏈接和DLL卸載可能會發生,但C++標準沒有描述動態鏈接加載或卸載。簡而言之,就是dll中的lambda,並且dll已經被卸載了?可能不會,或者你會問一個不同的問題。所以指針對於程序的生命週期是有效的。 – Yakk

相關問題