2017-03-10 43 views
4

我有一個回調系統,當發生什麼事情時,它會保存要發射的lambdas。要得到通知,您必須將lambda註冊到標識符,或者如果您不想再次收到通知,請取消註冊。如果我在lambda內部刪除包含lambda的對象,會發生什麼?

我的問題是,我已經註冊了lambdas,在調用時會從該系統取消註冊,導致正在執行的當前lambda的銷燬。我認爲這不安全。但我不確定。

簡化,例如:

#include <map> 
#include <functional> 
#include <iostream> 


int main() { 
    std::map<int, std::function<void()>> m; 
    m[10] = [&m]() { 
    int i = m.size(); // Just cheking the internal state of the lambda 
    m.clear(); 
    //i += m.size(); // If I uncomment this the std::cout is not working. 
    std::cout<< "What happens? " << i << std::endl; 
    }; 

    m[10](); 

    return 0; 
} 

我所看到的是,當我m.clear()後檢查拉姆達的狀態,我得到奇怪的行爲(例如std::cout不工作)。你能解釋一下在這些情況下究竟發生了什麼?

你將如何處理這些回調的情況?在調用回調之前製作副本(似乎是否定)?

+0

這裏我可以重現它:http://cpp.sh/2kjzg – FrameBuffer

回答

5

想想發生的事情:你存儲與lambda表達式std::function<void()>內部產生一個函數對象

std::function現在擁有所生成函數對象。它也位於std::map之內。

然後,通過參考捕捉相同std::map並在其上調用std::map::clear,取出存儲std::function

std::map::clear文檔上cppreference.org

從容器中刪除所有元素。 使引用包含元素的引用,指針或迭代器失效。任何過去末端的迭代器仍然有效。

可以安全地假設clear ing std::map使存儲在其中的數據無效。因此,使用存儲在生成的函數對象內的數據是不安全的,並且可能導致未定義的行爲


這是你在做什麼粗糙簡化:

using func = std::function<void()>; 

func f; 
f = [&f]{ int a = 0; f.~func(); std::cout << a; }; 
相關問題