#cpp #qt #qt5
При соединении с указателями, которые находятся внутри локального map, вылетает программа с ошибкой: Segmentation fault. Если сделаю мап статик или как поле, то все будет работать. Вопрос: почему ломается коннект, если map хранит указатели на объекты, а не сами объекты? Какие решение есть, кроме как статик? Вот пример, который смог сделать: someobj.h #ifndef SOMEOBJ_H #define SOMEOBJ_H #include#include class SomeObj : public QObject { Q_OBJECT public: explicit SomeObj(QObject *parent = nullptr) : QObject(parent) { } public slots: void someSlot() { qDebug() << "someSlot"; } }; #endif // SOMEOBJ_H mainwindows.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include "someobj.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; SomeObj obj[7]; }; #endif // MAINWINDOW_H mainwindow.cpp #include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QMap m { { ui->pushButton, &obj[0] }, { ui->pushButton_2, &obj[1] }, { ui->pushButton_3, &obj[2] }, { ui->pushButton_4, &obj[3] }, { ui->pushButton_5, &obj[4] }, { ui->pushButton_6, &obj[5] }, { ui->pushButton_7, &obj[6] } }; for (auto it = m.begin(); it != m.end(); ++it) { connect( it.key(), &QPushButton::clicked, [=] () { it.value()->someSlot(); qDebug() << it.key()->objectName(); ui->btnStop->setEnabled(true); }); } } MainWindow::~MainWindow() { delete ui; } UPD1: а почему нельзя вызвать sender() в анонимной функции? UPD2: При раскомменчивании любой строчки программа вылетает. for (auto it = m.begin(); it != m.end(); ++it) { connect( it.key(), &QPushButton::clicked, [=, obj = it.value(), btn = it.key()] () { // obj->someSlot(); // #1 // qDebug() << sender()->objectName(); // #2 qDebug() << obj->objectName(); // работает qDebug() << btn->objectName(); // работает ui->btnStop->setEnabled(true); }); } UPD3: При попытке: connect( it.key(), &QPushButton::clicked, [obj = it.value(), btn = it.key(), ui] () {... вылетает ошибка 'ui' in capture list does not name a variable. Поэтому так: connect( it.key(), &QPushButton::clicked, [obj = it.value(), btn = it.key(), uii = ui] () { // obj->someSlot(); // #1 // qDebug() << sender()->objectName(); // #2 qDebug() << obj->objectName(); // работает qDebug() << btn->objectName(); // работает uii->btnStop->setEnabled(true); }); И так, уже функция sender() не видна, тк this не передается. Но почему при раскомменчивании #1 программа вылетает? UPD4: все договариваю. Могу проект скинуть. Класс SomeObj не изменял.Конструктор MainWindow изменил так: MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QMap m { { ui->pushButton, &obj[0] }, { ui->pushButton_2, &obj[1] }, { ui->pushButton_3, &obj[2] }, { ui->pushButton_4, &obj[3] }, { ui->pushButton_5, &obj[4] }, { ui->pushButton_6, &obj[5] }, { ui->pushButton_7, &obj[6] } }; for (auto it = m.begin(); it != m.end(); ++it) { connect( it.key(), &QPushButton::clicked, [obj = it.value(), btn = it.key(), btnS = this->ui->btnStop] () { // obj->someSlot(); // #1 // qDebug() << sender()->objectName(); // #2 qDebug() << obj->objectName(); // работает qDebug() << btn->objectName(); // работает btnS->setEnabled(true); }); } }
Ответы
Ответ 1
"Теоретически" ваш map хранит указатели на интересующие вас объекты и в правильно написанном коде время жизни самого map не должно влиять на работоспособность вашего кода. Однако вы написали вашу лямбда-функцию так, что она занимается захватом итераторов этого map и всю работу делает через эти итераторы. В такой ситуации, как только map прекращает свое существование, попытки доступа через её итераторы приводят к падению программы. Прекратите захватывать итераторы и перепишите свою лямбду так, чтобы она захватывала значения указателей it.key() и it.value() и далее работала именно через захваченные указатели, а не через итератор. Таким образом вы полностью отвяжете вашу лямбду от этого временного map [=, obj = it.key(), button = it.value()] () { obj->someSlot(); qDebug() << button->objectName(); ui->btnStop->setEnabled(true); } Более того, при создании долгоживущих лямбд я бы посоветовал вам не пользоваться механизмом неявного захвата. Лучше прописывайте все захваты явно, чтобы отдавать себе отчет в том, что именно вы захватываете и к каким последствиям это может привести [obj = it.key(), button = it.value(), ui = this->ui] () { obj->someSlot(); qDebug() << button->objectName(); ui->btnStop->setEnabled(true); }
Комментариев нет:
Отправить комментарий