【问题标题】:Different definitions of the same lambda同一个 lambda 的不同定义
【发布时间】:2018-06-23 05:01:45
【问题描述】:

我最近开了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 函数的定义位置和方式。

【问题讨论】:

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


    【解决方案1】:

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

    但是,lambda 对象可以转换为 std::function。所以发生的事情是编译器创建了一个临时的std::function,它绑定到那个常量引用。在您的原始问题中创建非常相同的情况。因为每次调用tester 都需要另一个临时对象。临时性的人只能活到使他们栩栩如生的完整表达的尽头。

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

    【讨论】:

    • 谢谢@StoryTeller,很好的解释。
    猜你喜欢
    • 2023-01-21
    • 1970-01-01
    • 2011-09-30
    • 2020-11-25
    • 2017-10-01
    • 2013-07-21
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多