在Qt中从对象的析构函数发出信号是否可以?

sas*_*alm 15 c++ qt

当一个QObject派生的对象被破坏时,从它的析构函数发出信号是否可以?我尝试了它似乎工作,但我不确定是否应该这样做.

例如,这段代码

class MyClass : public QObject {
signals:
    void mySignal(const QString &str);
public:
    QString myString;
    ~MyClass() { emit mySignal(myString); }
}
Run Code Online (Sandbox Code Playgroud)

会在执行连接的插槽时将const引用传递给可能超出范围的对象.

Joh*_*itb 14

排放通常很好(QObject也会使用"已破坏"的信号),包括你的情况.当连接是直接连接时,字符串仍然存在.当它是QueuedConnection时,则首先将字符串复制到事件循环中.

  • 是的,当然.如果您有排队连接,则如果在dtor中发出信号,则不得使用sender().信号接收器必须意识到这一点. (3认同)

FPG*_*ior 5

如果您问是否可以:是的,它本身不会引起任何问题。

如果您要问在 Qt 中这样做是否通常安全?绝对不安全。如果你从析构函数中发出,你必须非常注意你所做的,并且对 Qt 事件系统有很好的理解。

请记住,当QObject后代析构时,它会断开所有信号的连接,因此被析构的对象不会再对其插槽进行调用?那么有一个问题:销毁命令。在QObject析构函数确实是断开的,也是最后毁灭,这意味着,在杀伤链事件可能仍然到达了“半死不活”的对象,从而导致访问冲突访问虚拟功能,并且已经破坏后代的成员时。如果您使用事件系统,并且满足以下任何条件,则存在可能性:

  • 在多线程环境中,如果对象没有在它自己的线程上被破坏。
  • 在多线程环境中,如果对象的销毁链触发 aprocessEvents()在任何运行路径上的运行。
  • 在多线程环境中,如果另一个线程上的任何对象与该对象有直接连接,并且在直接连接中无法对其销毁信号做出反应。
  • 在单线程环境中,当析构函数发送可能返回到直接连接链中的对象的信号时。

我称这种效果为“生与死”,processEvents()在析构函数中发出信号或运行任何形式的(通常是意外)会增加产生此类错误的机会。

当然,如果你能以某种方式保证在销毁过程中没有任何当前或未来的代码实际上会触发任何插槽,那么从析构函数中发出它是完全安全的,但是很难给出这样的保证,我建议尽可能避免它.