For a small GUI I first wanted to use function pointers; after reading lots of stuff I find that Lambda Callback Functions might be a better solution for this (?).
I always get a read access violation and guess I'm missing some important knowledge. It makes no difference if I use the copy or reference constructor in the lambda-call - I still get the exception.
#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();
}
The problem here is that function<void()> const &callback;
doesn't extend the life of the temporary std::function
that is generated from
btn = new Button([=]() {
//cout << "you clicked the button" << endl;
buttonClicked();
});
A lambda is not a std::function
so when you do the above the temporary std::function
is generated. You then bind to that temporary with callback
but const&
member variables do not extend the lifetime of the temporary they bind to. Only function local const&
get that behavior. That means when you exit VideoPreview
's constructor you are left with a button that has a function reference to a destroyed object.
To fix this just store callback
by value like
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.
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With