Нарушение доступа к чтению после лямбда-обратного вызова - PullRequest
0 голосов
/ 28 января 2019

Для небольшого графического интерфейса я сначала хотел использовать указатели на функции;прочитав много материала, я обнаружил, что лямбда-функции обратного вызова могут быть лучшим решением для этого (?).

Я всегда получаю нарушение прав чтения и думаю, что мне не хватает некоторых важных знаний.Не имеет значения, если я использую конструктор копирования или ссылки в лямбда-вызове - я все еще получаю исключение.

#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();
}

1 Ответ

0 голосов
/ 28 января 2019

Проблема здесь в том, что function<void()> const &callback; не продлевает жизнь временного std::function, который генерируется из

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

Лямбда не является std::function, поэтому, когда вы делаете вышевременный std::function генерируется.Затем вы привязываетесь к этому временному с помощью callback, но const& переменные-члены не продлевают время жизни временного, с которым они связываются.Только функция local 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.
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...