Lambda没有正确捕获变量

时间:2014-12-31 19:43:34

标签: c++ lambda closures

我对C ++ lambdas和变量捕获(通过引用)有点问题。一个lambda捕获变量以更改其值,而另一个lambda捕获它以读取值。一切都在同一个线程上运行。

bool isRunning = true; // variable to be captured

Cedar::Input input;
input.registerOnQuit([&]()->void {
    isRunning = false; // wrong address, value is constrained to lambda
});

Cedar::Platform platform;
platform.run([&](double t, double dt)->bool {
    input.pump(); // internally fires the handler passed to registerOnQuit()
    return isRunning; // correct address
});

如果有任何帮助,在内部使用void指针将lambdas装入C回调中。但是,我怀疑这就是问题所在,因为从本质上讲,两个lambdas正在经历完全相同的过程而一个是有效的,而另一个则没有。

// boxes the broken lambda
using OnQuit = std::function<void()>;
void registerOnQuit(OnQuit event) {
    Cedar_Input_registerOnQuitC([](void *data)->void {
        (*(OnQuit *)data)();
    }, (void *)&event);
}

// boxes the working lambda
using Hook = std::function<bool(double, double)>;
void run(Hook hook) {
    Cedar_Platform_runC([](double t, double dt, void *data)->bool {
        return (*(Hook *)data)(t, dt);
    }, (void *)&hook);
}

我提供了Cedar::InputCedar::Platform类字段来存储lambda的副本。

// fix to Cedar::Platform::run() is similar
using OnQuit = std::function<void()>;
void registerOnQuit(OnQuit event) {
    m_onQuit = event;
    Cedar_Input_registerOnQuitC([](void *data)->void {
        (*(OnQuit *)data)();
    }, (void *)&m_onQuit);
}

1 个答案:

答案 0 :(得分:1)

您正在存储悬空指针:

void registerOnQuit(OnQuit event) {
    Cedar_Input_registerOnQuitC([](void *data)->void {
        (*(OnQuit *)data)();
    }, (void *)&event);  // <-- saving a pointer to event here

    // <-- event goes out of scope here
}

这是未定义的行为。你在其他情况下做同样的事情,它恰好在那里工作。