廣義捕獲
Version >= C++ 14
Lambdas 可以捕獲表示式,而不僅僅是變數。這允許 lambdas 儲存僅移動型別:
auto p = std::make_unique<T>(...);
auto lamb = [p = std::move(p)]() //Overrides capture-by-value of `p`.
{
p->SomeFunc();
};
這將外部 p
變數移動到 lambda 捕獲變數,也稱為 p
。lamb
現在擁有 make_unique
分配的記憶體。因為閉包包含一個不可複製的型別,這意味著 lamb
本身是不可複製的。但它可以移動:
auto lamb_copy = lamb; //Illegal
auto lamb_move = std::move(lamb); //legal.
現在 lamb_move
擁有記憶。
請注意,std::function<>
要求儲存的值是可複製的。你可以編寫自己的僅移動要求 std::function
,或者你可以將 lambda 填充到 shared_ptr
包裝器中:
auto shared_lambda = [](auto&& f){
return [spf = std::make_shared<std::decay_t<decltype(f)>>(decltype(f)(f))]
(auto&&...args)->decltype(auto) {
return (*spf)(decltype(args)(args)...);
};
};
auto lamb_shared = shared_lambda(std::move(lamb_move));
獲取我們的僅移動 lambda 並將其狀態填充到共享指標然後返回可以複製的 lambda,然後儲存在 std::function
或類似的中。
廣義捕獲使用 auto
型別推導變數的型別。預設情況下,它會將這些捕獲宣告為值,但它們也可以是引用:
int a = 0;
auto lamb = [&v = a](int add) //Note that `a` and `v` have different names
{
v += add; //Modifies `a`
};
lamb(20); //`a` becomes 20.
Generalize 捕獲根本不需要捕獲外部變數。它可以捕獲任意表示式:
auto lamb = [p = std::make_unique<T>(...)]()
{
p->SomeFunc();
}
這對於為 lambda 提供它們可以容納和可能修改的任意值非常有用,而無需在 lambda 外部宣告它們。當然,只有在 lambda 完成其工作後你不打算訪問這些變數時,這才有用。