返回包含从函数捕获的 lambda

Returning a lambda with captures from a function

本文关键字:lambda 函数 包含 返回      更新时间:2023-10-16

在 C++11 中,人们可以用捕获来编写 lambda(这太棒了!

auto myfunc = [&] (int i) {return i + j;}; // j being somewhere in the lambda's context

那真是太棒了!但是,如果可以从函数甚至从另一个 lambda 返回这样的 lambda,那就太好了。这可能吗?

在 C++11 中,您必须将其包装在已知类型的函数对象中才能从函数返回它:

std::function<int(int)> get_lambda() {
    return [&] (int i) {return i + j;};
}

在 C++14 中,您可以使用 auto 返回 lambda 类型本身:

auto get_lambda() {
    return [&] (int i) {return i + j;};
}

在任何一种方言中,您都可以从lambda返回它:

auto get_lambda = [&] {return [&] (int i) {return i + j;};};

请注意,您不希望返回此特定 lambda,因为它捕获了对局部变量 j 的引用。当函数返回时,变量将被销毁,使引用无效。

您可以返回带有捕获的 lambda。由于 c++14 引入了自动返回类型,这特别容易。

下面是一个如何创建一个函数的示例,该函数将应用二进制运算符(此处为乘法,但它是一个模板参数,因此您可以为其提供任何内容(,其中一个参数在创建期间固定,第二个参数在调用期间提供

#include <iostream>
#include <functional>
template<typename F, typename T>
auto opby(F func, T arg)
{
    return [=](auto val) {
        return func(val, arg); 
    };
}

int main()
{
 auto mu = opby(std::multiplies<int>(), 2); 
 std::cout << mu(3) << std::endl;
}

它打印 6。返回的 lambda 已按值捕获其封闭范围,因此创建了一个函数,该函数将乘以 2 您将给它的任何参数。

唯一需要注意的是引用捕获时:您必须确保闭包不会超过捕获对象的生命周期。

我想提供一个接受答案的简单例子。

#include <iostream>
using namespace std;
auto get_lambda(int j) {
    //capture by value here
    return [=](int i) {return i + j; };
}
int main() {
    auto f = get_lambda(3);
    for (int i = 0; i < 1000; i++) {
        cout << f(i) << endl;
    }
}

这看起来就像JavaScript和Python中的闭包。哗啦啦!