Qt对象仍然可以在没有事件循环的情况下删除Later()吗?

Hal*_*aar 3 c++ qt

我对Qt中的线程和事件循环感到困惑.

一个QThread的正常运行exec()run().但是当你覆盖时run(),就不会有事件循环.

这个(较旧的)doc声明调用deleteLater()在没有事件循环的线程中创建的对象不起作用:

如果没有运行事件循环,则不会将事件传递给对象.例如,如果在线程中创建QTimer对象但从不调用exec(),则QTimer将永远不会发出其timeout()信号.调用deleteLater()也不起作用.(这些限制也适用于主线程.)

但是,请查看以下代码:

class MyObject : public QObject
{
    Q_OBJECT

    QString content;

public:
    MyObject(QObject *parent = 0);
    ~MyObject();
};

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    void run();

signals:

public slots:

};

MyObject::MyObject(QObject *parent) :
    QObject(parent),
    content("foobar")
{}

MyObject::~MyObject()
{
    // This code is still executed before I close the program. How?
    qDebug() << "Destroying MyObject";
}

MyThread::MyThread(QObject *parent) :
    QThread(parent)
{}

void MyThread::run()
{
    // Creating a heap object in a thread that does not have 
    // an event loop (because I reimplemented run()).
    MyObject * objectification = new MyObject();
    sleep(1);
    objectification->deleteLater();
}
Run Code Online (Sandbox Code Playgroud)

那么为什么这个deletelater()电话仍然会发布一个被接收的事件?

The*_*ght 6

正如Qt docs状态为deleteLater: -

从Qt 4.8开始,如果在一个没有运行事件循环的线程中的对象上调用deleteLater(),则在线程完成时将销毁该对象.

当没有事件循环时,仍然会删除该对象.如果查看QObject :: deleteLater 的源代码,您会看到发布了一个事件: -

void QObject::deleteLater()
{
    QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
Run Code Online (Sandbox Code Playgroud)

那么,让我们看一下删除线程时会发生什么.QThreadData的析构函数包括: -

for (int i = 0; i < postEventList.size(); ++i) {
    const QPostEvent &pe = postEventList.at(i);
    if (pe.event) {
        --pe.receiver->d_func()->postedEvents;
        pe.event->posted = false;
        delete pe.event;
    }
}
Run Code Online (Sandbox Code Playgroud)

如我们所见,虽然没有事件循环,但事件列表仍然可用.

如果我们更仔细地查看QThreadPrivate(仅以一个平台为例,在本例中为unix),您将看到当线程完成时,它会转发所有延迟删除的消息,以便继续处理它们:

QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
Run Code Online (Sandbox Code Playgroud)