Why is QObject destroyed signal called AFTER the destruction?

11,311

Solution 1

If you think about how the signal would get emitted, it's done by the base QObject - that's how the QObject knows it's being destroyed.

So when the derived class is destroyed, the most derived destructor gets run first (per standard C++ dtor handling), and the "MyObject destructor" message is displayed. When that dtor completes, the base dtors get run and in this case that's the QObject dtor, which then emits the signal and the "About to be destroyed!" message is displayed.

The wording in the docs you mentioned might be a bit imprecise. It might be better worded with something like, "This signal is emitted as the object obj is destroyed" or "This signal is emitted immediately before the object obj is completely destroyed".

Solution 2

Michael's answer is correct insofar direct connections are used.

If queued connections are used, the slots are called at the next iteration of the main event loop. Combine that with the destructor of the object emitting the signal, it becomes obvious why the result is the same as for direct connections are involved.

See also the official docs:

Note that Connection type may have consequences for threaded programming. (Short version: Direct executes slot in the same thread as the signal, but queued runs in the receiver thread)

Share:
11,311
lamefun
Author by

lamefun

Updated on June 15, 2022

Comments

  • lamefun
    lamefun almost 2 years

    Consider this test case:

    class MyObject : public QObject
    {
        Q_OBJECT
    public:
        MyObject() { qDebug() << "MyObject constructor"; }
        virtual ~MyObject() { qDebug() << "MyObject destructor"; }
    };
    
    class Tracker : public QObject
    {
        Q_OBJECT
    public:
        Tracker() {}
    
    public slots:
        void onDestructor() { qDebug() << "About to be destroyed!"; }
    };
    
    int main(int argc, char** argv)
    {
        QCoreApplication app(argc, argv);
    
        Tracker tracker;
    
        MyObject *obj = new MyObject();
        QObject::connect(obj, SIGNAL(destroyed()), &tracker, SLOT(onDestructor()));
        delete obj;
    
        return app.exec();
    }
    

    It prints this:

    MyObject constructor
    MyObject destructor
    About to be destroyed!
    

    This behaviour contradicts the Qt documentation: "This signal is emitted immediately before the object obj is destroyed, and can not be blocked." Why does this happen?