在QT中,从closeEvent函数发出信号是否安全?

时间:2014-02-05 11:03:37

标签: c++ qt

请考虑以下代码

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
   }
}

安全吗?我冒险崩溃导致对象obj在发出信号之后和cleanUp函数返回之前被销毁了吗?

非常感谢。

1 个答案:

答案 0 :(得分:3)

这是因为信号/槽系统的功能类似于函数调用(添加了“连接”机制),如the Qt Documentation about Signals and Slots中所述。

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

因此,在您的情况下,A对象仍然存在且有效。请注意,关闭窗口小部件不一定会删除它(如注释中的vahancho所述)。

编辑实际上,这取决于您是否通过cleanup 中的指针操纵A.如果B没有存储指向A的指针,那么无论如何都会没问题(因为无论如何都会发出信号,将调用插槽,如果A不是'在插槽内访问,根本没有问题,无论指定或假设的连接类型。如果cleanup以某种方式通过指针访问A,请阅读以下内容:

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

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