对于一个小的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();
}
答案 0 :(得分:9)
这里的问题是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.
}
};