同一个lambda的不同定义

时间:2018-01-14 09:18:41

标签: c++ c++11 lambda closures

我最近开了this次讨论,其中出现了以下问题。这个问题是一种持续的讨论。这是代码:

#include <iostream>
#include <functional>

using namespace std;

std::function<int(void)> mylambda(int starter){
    return [starter]() mutable {
        return ++starter;
    };
}

void tester_wrapper(const std::function<int(void)>& cb, int counter){
    if (counter == 10)
        return;
    else{
        cout << cb() << endl;
        tester_wrapper(cb, counter + 1);
    }
}

void tester(const std::function<int(void)>& cb){
    tester_wrapper(cb, 0);
}

int main()
{
    auto getNum = mylambda(1);

    tester(getNum);
    tester(getNum);
}

在这种情况下,代码执行我的预期,更具体地说,它打印从2到21的所有数字。但是,如果我的main函数是这样的:

int main()
{
    auto getNum = ([](int starter) {
        return [starter]() mutable {
            return ++starter;
        };
    })(1);

    tester(getNum);
    tester(getNum);
}

然后输出将是重复两次的2到11的数字。即使两段代码之间的唯一区别在于mylambda函数的定义位置和方式,我也无法解释自己为什么产生这个输出。

1 个答案:

答案 0 :(得分:8)

因为lambda闭包类型和std::function不是引用相关的。这些是不同的类型。您不能将对std::function的引用直接绑定到lambda对象。

然而,lambda对象可以转换为std::function。所以会发生什么是编译器创建一个绑定到该const引用的临时std::function。在原始问题中创建非常相同的情况。因为每次调用tester都需要另一个临时对象。临时工作只能活到完全表达的终点,使它们恢复活力。

在第一个代码示例中,main中已经有一个std::function对象。那个直接绑定到引用,因此您使用相同的引用对象调用tester