广义捕获
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 完成其工作后你不打算访问这些变量时,这才有用。