c++ - 同一个lambda的不同定义

标签 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 函数的定义位置和方式。

最佳答案

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

但是,lambda 对象可以转换为 std::function。因此,编译器会创建一个绑定(bind)到该常量引用的临时 std::function。在您的原始问题中创造非常相同的情况。因为每次调用 tester 都需要另一个临时对象。临时对象只会活到使它们焕然一新的完整表达的尽头。

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

关于c++ - 同一个lambda的不同定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48248176/

相关文章:

c++ - 不同消息的 OpenSSL 签名长度不同

c++ - 是否保证 std::unique_ptr 删除顺序?

c++ - 在 C++/Qt 中作为 lambda 函数参数的槽

c# - 没有声明的 Lambda 表达式?

java - Java 8 中的 lambda 表达式是否执行多线程?

c++ - 如何摆脱 FormatMessageA 错误消息中附加的 ".\r\n"字符?

c++ - VIsual Studio 说我在字符串中有错误

c++ - 将 NT 文件时间转换为 Win32 时间

C++ - 编译器如何决定以引用类型作为参数的重载函数?

qt - 如何在 QJsonArray 中使用基于 C++11 范围的 for