deleteLater函数使用

背景

之前有一个需求:在业务的某个阶段通过new方式创建了一个qmessagebox对象,点击该弹窗对象的按钮后删除该弹窗对象。

解决方法:采用信号槽的方式,点击弹窗上的按钮后,qmessagebox对象会发送buttonClicked(QAbstractButton*)信号,在该弹窗的信号的槽函数中,通过QObject提供的方法sender()可以获取发送信号的对象指针,然后对该指针调用deleteLater接口。起初采用的是在槽函数中直接调用delete删除对象,但是程序崩溃,分析原因应该是因为是同一个线程内的函数调用,相当于是同步调用,此时该对象业务逻辑还没有执行完成,删除该对象造成程序异常,导致程序崩溃。如果是异步调用应该没有问题,后面会专门写一篇文章分析qt信号槽的同步异步机制。

deleteLater接口总结

  • deleteLater是QObject的成员函数,用于延迟删除QOjbect对象,对于以Qobject为基类的对象推荐使用deleteLater而非delete。
  • deleteLater作用的对象必须是以QObject对象为基类的。并且类的声明中包含Q_OBJECT宏。因为其本质是在deleteLater的实现中发送了事件,要删除的对象接收该事件后再进行删除动作。事件名称为DeferrerDelete,原理如下:
void QObject::deleteLater()
{
    QCoreApplication::postEvent(this, new QDeferredDeleteEvent());
}
...
bool QObject::event(QEvent *e)
{
    switch (e->type()) {
    ....
    case QEvent::DeferredDelete:
        qDeleteInEventHandler(this);
        break;
    ....
    }
}
...
void qDeleteInEventHandler(QObject *o)
{
    delete o;
}
  1. 调用QCoreApplication接口自己给自己发送 QDeferredDeleteEvent事件
  2. 在Qobject的event的实现中包含了对QDeferredDeleteEvent事件的处理
  3. 销毁对象
  • 调用deleteLater后,至少在一个函数中依然可以访问该对象,因为原因是该对象还存在。

你可能感兴趣的:(Qt,qt)