廣義捕獲

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 捕獲變數,也稱為 plamb 現在擁有 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 完成其工作後你不打算訪問這些變數時,這才有用。