在QT中,从CloseEvent函数发出信号是安全的

In QT is it safe to emit a signal from a closeEvent function?

本文关键字:信号 安全 函数 QT CloseEvent      更新时间:2023-10-16

请考虑以下代码

class A : public QWidget
{
    signals:
       void readyToBeClosed();
    protected:
       void closeEvent(QCloseEvent* e)
       {
           QWidget::closeEvent(e);
           emit readyToBeClosed();
       }
}
class B: public QWidget
{
public:
   B(A* obj)
   {
       connect(obj,SIGNAL(readyToBeCLosed()),this,SLOT(cleanUp());
   }
private slots:
   void cleanUp()
   {
        //DO SOMETHING
   }
}

安全吗?我可以冒着崩溃的风险导致对象在发射信号后和清理功能返回之前被销毁吗?

非常感谢。

是,因为信号/插槽系统的工作方式与函数调用(添加了"连接"机制),如QT文档中指定的有关信号和插槽的指定。

发出信号时,所有连接到它的插槽都会被调用,一旦它们返回,控件将返回到发出信号的代码。因此,在信号之后,closeEvent函数中的下一行代码将在连接到此信号的所有插槽后执行。

因此,在您的情况下,一个对象仍然存在并且有效。请注意,关闭小部件不一定会删除它(如Vahancho在评论中指出的那样)。

edit 实际上,它是否取决于您是否通过cleanup 中的指针来操作。如果B不存储A的指针,无论如何都可以(因为信号会发出,插槽都会被调用,并且插槽内无法访问A,那将是没有问题的已指定或假定的连接类型)。如果cleanup以某种方式通过指针访问A,请阅读以下内容:

正如指出的那样,我确实应该先证明只有在使用Qt::DirectConnection模式进行此连接时,情况才是这种情况。确实,此模式产生了我描述的行为,并被假定(connect函数的默认参数是Qt::AutoConnection,它会根据上下文自动选择,即从线程到从另一线程中运行的插槽的信号)

如果您使用Qt::QueuedConnectionQt::AutoConnection假设的情况,那么您确实可以具有未定义的行为,因为对插槽的调用将排队到接收器线程,并且只有在控制返回该线程的事件循环后才执行。如果在A实际破坏后发生这种情况,