c++ - 我怎样才能让 QThread 在不泄漏的情况下发出堆分配的 QObject?

标签 c++ multithreading qt memory-leaks signals-slots

我的情况是我有一个 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);

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

关于c++ - 我怎样才能让 QThread 在不泄漏的情况下发出堆分配的 QObject?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37956073/

相关文章:

c - 如何退出被信号量挂起的线程?

C++ cout操作数错误,类型错误ostream,字符串

c++ - D 是否有类似于 C++0x 的 move 语义的东西?

c++ - 当 TFramedTransport 打开时,thrift 中的 TNonblockingServer 崩溃

java - 多线程环境下迭代集合: ConcurrentModificationException

html - Qt - 获取托管在 Internet 上的网页的源代码(HTML 代码)

c++ - 在 c++ 中的不同行或列旁边搜索最小值和最大值的最快方法是什么

c++ - boost::this_thread::sleep_用于使整个程序休眠

qt - 在 Qt 中的应用程序窗口之间切换的最佳实践是什么?

c++ - 使用导入的 makefile 将 Qt Creator .config 添加到 .h