C++ 广义捕获

示例

C ++ 14

Lambda不仅可以捕获变量,还可以捕获表达式。这允许lambda存储仅移动类型:

auto p = std::make_unique<T>(...);

auto lamb = [p = std::move(p)]() //覆盖“ 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) //注意`a`和`v`具有不同的名称
{
  v += add; //修改`a`
};

lamb(20); //a变成20。

通用捕获根本不需要捕获外部变量。它可以捕获任意表达式:

auto lamb = [p = std::make_unique<T>(...)]()
{
    p->SomeFunc();
}

这对于为lambda提供可以保留并可能修改的任意值很有用,而不必在lambda外部声明它们。当然,这仅在您不打算在lambda完成其工作之后访问这些变量的情况下才有用。