Попробовал передать умный указатель std::unique_ptr через сигнал/слот и получил ошибку из за удаленного конструктора копирования (unique_ptr(const unique_ptr&) = delete;). Так можно ли использовать умный указатель std::unique_ptr в сигнал/стол? UDP: нельзя!
Связный вопрос: Как передавать большие контейнеры между потоками?
Переделал класс под указатель std::shared_ptr<Data>. Используя замечания @yrHeTaTeJlb, вызываю: Q_DECLARE_METATYPE(std::shared_ptr<Data>); и qRegisterMetaType<std::shared_ptr<Data>>("shared_ptr<Data>");. И все заработало.
Вывод qDebug():
Data();
finish
~Data();
mainwwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMap>
#include <memory>
class Data {
QMap<int, QString> _m; // большие
std::array<QString, 1024*1024> _a;
public:
Data() { qDebug() << "Data();"; }
~Data() { qDebug() << "~Data();"; }
void initData();
};
Q_DECLARE_METATYPE(std::shared_ptr<Data>);
class Worker : public QObject {
Q_OBJECT
std::shared_ptr<Data> _d;
public:
Worker() : QObject(), _d(std::make_shared<Data>()) { }
signals:
void finished(std::shared_ptr<Data> d);
public slots:
void process() { _d->initData(); emit finished(_d); }
};
class Controller : public QObject {
Q_OBJECT
std::shared_ptr<Data> _d;
public:
Controller(QObject *parent = nullptr) : QObject(parent) { }
void start();
signals:
void finished(std::shared_ptr<Data> d);
};
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
Controller _c;
std::shared_ptr<Data> _d;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QStandardItemModel>
#include <QThread>
void Data::initData() { /*some init code*/ }
void Controller::start() {
QThread *thr = new QThread;
Worker *w = new Worker;
w->moveToThread(thr);
connect(thr, &QThread::started, w, &Worker::process);
connect(w, &Worker::finished, this, &Controller::finished);
connect(w, &Worker::finished, thr, &QThread::quit);
connect(w, &Worker::finished, w, &Worker::deleteLater);
connect(thr, &QThread::finished, thr, &QThread::deleteLater);
thr->start();
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
qRegisterMetaType<std::shared_ptr<Data>>("shared_ptr<Data>");
ui->setupUi(this);
connect(&_c, &Controller::finished, this, [this] (std::shared_ptr<Data> d) { qDebug() << "finish"; _d = d; });
_c.start();
}
MainWindow::~MainWindow() { delete ui; }
По умолчанию connect выполянется с Qt::AutoConnection.
Если сигнал передается между потоками Qt::AutoConnection == Qt::QueuedConnection
Для того чтобы передавать объекты c Qt::QueuedConnection их тип нужно зарегистрировать через QMetaType::qRegisterMetaType.
Для этого тип нужно сначала объявить через Q_DECLARE_METATYPE.
Q_DECLARE_METATYPE требует чтобы у класса был конструктор копирования, а у std::unique_ptr его нет.
Таким образом передать std::unique_ptr через сигнал из потока в поток не получится.
Продвижение своими сайтами как стратегия роста и независимости