读取 Lambda 回调后的访问冲突



对于一个小的GUI,我首先想使用函数指针;在阅读了很多东西之后,我发现Lambda回调函数可能是更好的解决方案(?)。

总是收到读取访问冲突,并猜测我缺少一些重要知识。 如果我在 lambda 调用中使用复制或引用构造函数没有区别 - 我仍然得到异常。

#include <iostream>
#include <functional>
using namespace std;
//=======================================================
class Button {
private:
    function<void()> const &callback;
public:
    Button(function<void()> const &c) : callback(c) {
        cout << "created Button" << endl;
        callback();     // THIS CALL WORKS FINE
    }
    void update() {
        // if(clicked)...
        callback();     // HERE I GET THE READ ACCESS VIOLATION
    }
};
//=======================================================
class VideoPreview {
private:
    Button *btn;
public:
    VideoPreview() {
        cout << "created VideoPreview" << endl;
        btn = new Button([=]() {
            //cout << "you clicked the button" << endl;
            buttonClicked();
        });
    }
    void update() { // "check the gui"
        btn->update();
    }
    void buttonClicked() {
        cout << "you clicked the button" << endl;
    }
};
//=======================================================
void main() {
    VideoPreview foo;
    foo.update();
}

这里的问题是function<void()> const &callback;不会std::function延长从

btn = new Button([=]() {
    //cout << "you clicked the button" << endl;
    buttonClicked();
});

lambda 不是std::function因此当您执行上述操作时,会生成临时std::function。 然后,您可以使用callback绑定到该临时变量const&但成员变量不会延长它们绑定到的临时变量的生存期。 只有函数本地const&才能获得该行为。 这意味着当你退出VideoPreview 的构造函数时,你留下了一个按钮,该按钮具有对已销毁对象的函数引用。

要解决此问题,只需按值存储callback,例如

class Button {
private:
    function<void()> callback;
public:
    Button(function<void()> c) : callback(std::move(c)) {
        cout << "created Button" << endl;
        callback();     // THIS CALL WORKS FINE
    }
    void update() {
        // if(clicked)...
        callback();     // works now.
    }
};

最新更新