我的情况是,我有一个QWidget派生的类MyWidget,它将创建一个QThread派生的类(WorkerThread)来做一些不间断的阻塞其run()方法的工作。其结果是QObject派生类(DataClass)的堆分配实例,然后由MyWidget接收并处理该实例。不过,MyWidget是一个暂时性的小部件,由于用户的操作,在WorkerThread仍在运行时可能会删除它。

这是一些伪代码来说明这一点:

#include <QThread>
#include <QWidget>

class DataClass : public QObject {
    Q_OBJECT
public:
    // contains some complex data
};

class WorkerThread : public QThread {
    Q_OBJECT
public:
    virtual void run() {
        DataClass *result = new DataClass;
        doSomeReallyLongUninterruptibleWork(result);
        emit workComplete(result);
    }
signals:
    void workComplete(DataClass *);
};

class MyWidget : public QWidget {
    Q_OBJECT
public:
    void doBlockingWork() {
        WorkerThread *worker = new WorkerThread;
        connect(worker, &WorkerThread::finished, worker, &WorkerThread::deleteLater);
        connect(worker, &WorkerThread::workComplete, this, &MyWidget::processData);
        worker->start();
    }

public slots:
    void processData(DataClass *result) {
        // Do some stuff
        delete result;
        // Assuming MyWidget still exists when WorkerThread has finished, no memory has leaked
    }
};

通常,返回工作线程结果的正确“Qt”方法是使其发出一个信号,其参数是其工作的结果,如上所示。可以复制的数据很好,但是由于结果是指向堆分配对象的指针,因此我必须小心确保释放内存。

通常,这不会有问题,因为既然WorkerThread已经完成,我可以安全地将指向DataClass的指针传递给MyWidget,让它处理DataClass,然后释放它。

问题是,正如我之前所说,MyWidget是暂时的,可能在WorkerThread完成之前被销毁。在这种情况下,如何确保DataClass实例以一种或另一种方式释放?

特别是,我正在寻找对他们来说比较优雅的解决方案,这意味着它利用了Qt的功能,并且最好使它能够使WorkerThread保持与MyWidget的分离,从而使WorkerThread不需要了解任何信息或任何知识。其他可能创建它的类。我也乐于接受可以改善我已经在使用的模式的想法。

最佳答案

使用智能指针(例如QSharedPointer)代替普通指针:

DataClass *result = new DataClass;

应该替换为
QSharedPointer<DataClass> result = QSharedPointer<DataClass>(new DataClass);

然后,您可以安全地将其传递到某个地方,而不必担心将其删除。当它超出了可以使用它的最后作用域时,该对象将被自动销毁。

09-09 23:51