2013-10-09 42 views
5

我正在處理內存密集型應用程序,它應該正確處理內存不足的情況。關閉的捕獲變量存儲在哪裏?

我有類似

class memory_manager { 
    // returns true if slot created (and function is being run) 
    // false otherwise 
    static bool create_slot(int id, std::function<void (slot&)>); ........ 
} 

此類處理,日誌,等等所有的內存外的問題,保持所有插槽的所有權和驅動器並行。

不過,我有未處理的std::bad_alloc在下面的代碼:

slot_data_to_copy dat; 

memory_manager::create_slot(100, [&dat](slot& sx) { sx.assign_data(dat); }); 

我認爲扔在捕捉變量期間完成。 (我其實捕獲了更多,這只是一個示例)

閉包創建在哪裏? 我可以控制它嗎?或者,如果我以一種需要參數的方式更新管理器,如

slot_data_to_copy dat; 

memory_manager::create_slot<slot_data_to_copy> 
     (100, dat, [](slot& sx, slot_data_to_copy& dat) 
      { sx.assign_data(dat); } 
     ); 

是否保證它不會丟棄?我正在編譯使用Windows上的Visual C++和Linux上的GCC,但我只在Windows上觀察到這種行爲(在Linux上,我可能在內存不足的地方可能會處理它)。

編輯:

http://en.cppreference.com/w/cpp/utility/functional/function/function - 的std ::函數包含拋出異常商..我可能失去了一些東西,但哪一個是這個(拉姆達)情況下使用?

+0

'我假設在捕獲變量的過程中完成了拋出。 ' - lambda被複制到堆上?什麼時候發佈? – nothrow

+1

[expr.prim。lambda表達式的評估導致臨時值,該臨時值稱爲*閉包對象*。這裏使用的'std :: function'的ctor是'template < class F >函數(F f);',它*不是*'noexcept'。 – dyp

回答

4

閉合創建在哪裏?

一個lambda表達式創建一個未命名類型的對象,它只是一個普通的函子類。捕獲的變量是該未命名類型的成員。

您的代碼memory_manager::create_slot(100, [&dat](slot& sx) { sx.assign_data(dat); });本質上是一樣的:

slot_data_to_copy dat; 

struct unnamed_lambda_type { 
    slot_data_to_copy &dat; 

    unnamed_lambda_type(slot_data_to_copy &dat_) : dat(dat_) {} 

    void operator() (slot &sx) const { 
    sx.assign_data(dat); 
    } 
}; 

memory_manager::create_slot(100, unnamed_lambda_type(dat)); 

哪裏封閉產生的?

閉包對象就像任何其他臨時對象,通常在堆棧上分配。

1

關閉 the lambda;捕獲的變量是一個匿名結構的數據成員(這是lambda是什麼)。創建你的lambda不能拋出bad_alloc;你的錯誤在其他地方(可能是創建std::function,這可能會將lambda複製到堆上)。

旁註:您在lambda中通過引用捕獲;確保你的slot_data_to_copy dat在lambda被調用的時候沒有被銷燬。您應該按值複製它或立即調用lambda。

+0

好吧,我認爲這是在捕獲變量時完成的(如果它是在std :: function <>中創建的,我不介意)。我想要在堆棧上創建std ::函數,這可能嗎? – nothrow

+0

'std :: function'被作爲參數傳遞,因此它已經在堆棧中。 'std :: function'內部有一個指向堆上lambda的指針(想想'std :: vector'可以在堆棧上,但它的數據在堆上)。 – Simple

+0

ad sidenote - 函數create_slot不保存lambda表達式,所以數據不能被破壞 – nothrow