同一个lambda的不同定义

5

我最近开了一个讨论,下面的问题就是从那个讨论中出现的。这个问题是那个讨论的延续。以下是代码:

#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的数字重复两次。我无法解释为什么这段代码产生这样的输出,即使这两个代码片段之间唯一的区别就是lambda函数mylambda定义的位置和方式。
1个回答

8
由于lambda闭包类型和std::function不相关联,它们是独立的类型。你不能直接将引用绑定到lambda对象上。
然而,lambda对象可以转换为std::function。因此,编译器会创建一个临时的std::function来绑定到那个const引用上。这与你原始问题中的情况非常相似。因为每次调用tester都需要另一个临时对象。临时对象只存在于使它们产生的完整表达式的末尾。
在第一个代码示例中,你已经在main函数中拥有了一个std::function对象。它直接绑定到引用,因此你正在使用同一个所引用的对象调用tester函数。

谢谢@StoryTeller,解释得非常好。 - Marco Luzzara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接