C++ 广义捕获
示例
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完成其工作之后访问这些变量的情况下才有用。