前一篇提到 Lambda Capture by-value。這一篇說明 Capture by-reference——以 &
表示。
同樣分成兩種寫法:
底下程式碼用於展示 Lambda 的語法,其功能性不在討論範圍,切記。
std::vector<int> iv = {1, 1, 1, 2, 3, 4, 5, 6, 8};
int call_count = 0;
auto it = std::find_if(begin(iv), end(iv),
[&](int i)
{
++call_count;
return i > 6;
}
因為 [&]
的關係,上例中 Lambda 內的 call_count
為外部的一個參考,改變 call_count
的值,等於改變了外面的那個 call_count
的值。
上例中,call_count
以及 iv
皆可被 Lambda 以 by-reference 的方式使用,但其實只有 call_count
有用到。因此,上述例子可以改成以下較為安全的寫法:
std::vector<int> iv = {1, 1, 1, 2, 3, 4, 5, 6, 8};
int call_count = 0;
auto it = std::find_if(begin(iv), end(iv),
[&call_count](int i)
{
++call_count;
return i > 6;
}
如此一來,iv
確定無法被 Lambda 使用,這樣的「保證」在理解程式碼結構,以及問題發生時的除蟲,皆有助益。我建議沒有特殊考量的話,應優先使用 individual capture。
由於 Capture by-reference 可以參考到外部變數,在某種情況下,Lambda 被執行時已經離開該變數所在的 Scope,使用該變數會造成程式出問題,甚至當掉。因此,每用 Capture by-reference 時,都要先問:「Lambda 何時被執行?」
以 std::thread
為例:
std::vector<int> iv = {1, 1, 1, 2, 3, 4, 5, 6, 8};
int call_count = 0;
std::thread the_thread([&call_count, &iv]()
{
auto it = std::find_if(begin(iv), end(iv),
[&call_count](int i)
{
++call_count;
return i > 6;
}
});
the_thread.detach();
the_thread
執行時,call_count
以及 iv
已經不存在,不應該被使用。
想請問: 最後一個例子,call_count 以及 iv 不存在的原因是 ?
他不是先傳到一個 lambda 然後再傳到下一個 labmda ?
我的觀點是std::thread the_thread([&call_count, &iv]()
被執行的時候已經不在原本有 call_count 以及 iv 的Task Struct了
所以才沒有這兩變數