[英]What would a default lambda capture mode via init capture be like?
使用 lambda,在 C++11 中,我們可以將默認捕獲模式設置為按值/按引用,例如[=]
/ [&]
,對於某些變量,可選地后跟顯式捕獲,按引用/按值,例如[=,&this_is_by_ref]
或[&,this_is_by_value]
。
在 C++14 中,我們也可以通過移動進行顯式捕獲,例如[y = std::move(x)]
。
在Effective Modern C++中,第 32 項第 3 段,我讀到
您無法用 init 捕獲表達的一件事是默認捕獲模式,[...]
作者最有可能指的是什么?
我們已經有辦法通過復制或引用來捕獲我們需要的所有變量。 為什么我們要用x = y
的形式來表達呢?
也許作者僅指“默認移動捕獲”? 像[x = std::move(x), y = std::move(y), …]
一樣工作的東西,其中列出了正文中使用的所有變量?
該段落指出不可能將 init 捕獲與默認捕獲模式([&] 或 [=])結合使用,並且移動語義沒有新的默認捕獲模式。
我們已經有辦法通過復制或引用來捕獲我們需要的所有變量。 為什么我們要用 x = y 的形式來表達呢?
你的想法是正確的。 將初始捕獲與默認捕獲相結合將具有與舊的默認捕獲方式相同的行為。 也許這就是它被省略的原因。 然而 init-capture 可以做一些以前做不到的新事情。 (比如給一個新變量賦值)
也許作者僅指“默認移動捕獲”? 像 [x = std::move(x), y = std::move(y), …] 一樣工作的東西,其中列出了正文中使用的所有變量?
這也是事實。
為了更好地理解 init capture 的新可能性,我給你舉了這個小例子。 假設您要用 0 到 n 的值填充一個向量。 使用 lambda 執行此操作的舊方法是:
std::vector<int> vec;
int i = 0;
std::generate_n(std::back_inserter(vec), n, [i]()mutable{
return i++;
});
現在使用 init 捕獲,您可以在 lambda 捕獲中對計數變量進行值初始化:
std::vector<int> vec;
std::generate_n(std::back_inserter(vec), n, [i=0]()mutable{
return i++;
});
這在以前是不可能的,但在很多地方都很有用。
“init capture”是[z = y]
風格的捕捉。
您無法用這種捕捉方式表達的唯一捕捉方式是默認捕捉模式。 IE:
[&, z=y]{ /* some code */ }
這里&
使用的是舊式捕獲語法。 它表示我們有一個默認的捕獲模式。 z=y
是新式的“init capture”。
沒有辦法用“init capture”來表示默認的捕獲方式。
您使用舊式捕獲語法執行的任何其他操作,都可以使用 init 捕獲語法進行復制。
IE:
[x=x]{ /* some code */ }
是另一種表達方式
[x]{ /* some code */ }
和
[&x=x]{ /* some code */ }
是另一種表達方式
[&x]{ /* some code */ }
現在這不是那么深。
但是如果你的論點是“不要使用舊的捕獲語法”,你應該證明你不再需要它了。 並且您不需要舊的捕獲語法,除非您定義默認捕獲模式。
@OutOfBound 的回答已經很好了。 我只會從不同的角度表達類似的想法。
Scott Meyers 在第 32 項的前幾段中指出:
[&&, &&x]
),但最終選擇了一種不同的、更通用的方法:他們引入了一種新語法(“C+ +14 語法”)。另請注意,新的捕獲語法非常靈活,它不僅可以表達您使用移動語義的意圖,還可以用於 const 引用(Scott 省略了后一點)和可變 lambda。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.