2015-08-13 125 views
9

有人可以讓我看看下面的例子:C++ 11的λ:混合捕獲列表

1)拉姆達,通過價值捕獲xy作爲參考。如果未指定,其餘的默認值是什麼?

2)根據價值捕獲x的Lambda。 y作爲參考,所有其他的價值。

3)根據價值捕獲x的Lambda。 y作爲參考,其他所有參考。

而且,是它允許該2個lambda表達式在同一範圍內具有相同的捕獲簽名,如兩者是[],或兩者是[& X,=]

由於

回答

8

1)[x, &y](){}剩餘部分不捕獲

2)[=, &y](){}

3)[&, x](){}

捕獲-list是逗號分隔的零個或多個捕獲列表, 任選beginni使用capture-default。唯一的捕獲 默認值是&(通過引用)和=(按值)。如果使用捕捉默認值 ,則其他捕捉不能使用相同的捕捉類型。任何捕獲 可能只出現一次。

另外,是它允許該2個lambda表達式在同一範圍內具有相同的捕獲簽名,如兩者是[],或兩者是[& X,=]

當然是允許。每個lambda都將是不同的對象,並具有不同的類型。如果你通過兩個lambdas中的值捕獲變量,那麼每個lambda都會有它的副本。如果在兩個lambda表達式中通過引用捕獲變量,那麼每個lambda表達式都會引用同一個捕獲的變量。

2

1)

[x,&y](){} // the rest is not captured, eg `z` is not defined in the scope 

2)

[=,&y](){} // `=` is capture everything by value 

3)

[&,x](){} // `&` is capture everything by reference 
7

可以只寫一些例子:

int x = 7, y = 12, z = 24; 

auto lambda1 = [x, &y]{ 
    // can't do this... 
    // std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl; 
    std::cout << "x=" << x << ", y=" << y << std::endl; 
}; 

auto lambda2 = [=, x, &y]{ 
    std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl; 
}; 

auto lambda3 = [&, x, &y]{ 
    std::cout << "x=" << x << ", y=" << y << ", z=" << z << std::endl; 
}; 

++x, ++y, ++z; 
lambda1(); 
lambda2(); 
lambda3(); 

現在,這裏lambda1不能使用z。沒有「隱式」捕獲,因爲我們沒有指定=&並且z沒有出現在捕獲列表中,所以我們不能在那裏打印z。所以如果我們嘗試使用我已註釋過的行,那就錯了。

其他兩個都很好,分別打印7,13,24和7,13,25。請注意,=&必須先到。此外,考慮到我們捕捉所有通過值/基準,其他捕獲的一個是多餘的,這樣我們就可以做了:

auto lambda2 = [=, &y]{ ... }; 
auto lambda3 = [&, x]{ ... }; 
+0

原來'lambda2'和'lambda3'不應該編譯。一旦您指定了拍攝默認值,剩餘的顯式拍攝將無法指定相同的模式。 – Praetorian

+0

@Barry捕獲列表等[&中,x,&Y]或[=,X,&Y]無效。這是因爲:如果使用捕獲缺省情況下,沒有其他的捕獲可能使用相同的拍攝類型 –

+0

@Barry,可以請你到神冰毒的評論作出迴應? 這是什麼意思「捕獲默認」? 「剩餘的顯式捕捉不能指定相同的模式」是什麼意思? –

1

從他C++11 FAQ引述了Bjarne:

的[&]是一個「捕捉列表」,指定使用的本地名稱將通過引用傳遞。我們可以說,我們要「捕獲」只有V,我們可以這樣說:& V]。如果我們想通過價值傳遞v,我們可以這麼說:[= v]。捕獲沒有什麼是[],捕獲所有的引用是[&],並捕獲所有的值是[=]。 如果一個操作既不常見也不簡單,我推薦使用一個命名的函數對象或函數。