Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Table of Contents

  1. QObject classes
  2. Non-QObject classes
  3. Object destruction order
  4. Structs

Object Lifetime Management

QObject classes

Instances of the QObject class and classes derived from QObject are usually organized in trees. When a node in such a tree is destroyed, all its children will also be destroyed.

QObjects are NOT managed by the garbage collector in QtD. To avoid memory leaks, the programmer should manually destroy roots of unused QObject trees. Most of the time, it is sufficient to restrict lifetime of the root object to a lexical scope by using qtd.QtdObject.scoped construct:

void main()
{
    auto root = scoped!QObject; 
    auto child = new QObject(root);
    auto child2 = new QObject(child);
}

C++ equivalent:

int main(int argc, char *argv[])
{
    QObject root; 
    QObject *child = new QObject(&root);
    OObject *child2 = new QObject(child);

    return 0;
}

QtD objects can be manually destroyed by calling qtd.QtdObject.dispose function. Common scenarios:

void foo()
{
    auto root = new QObject;
    dispose(root);
}
class C
{
    QObject root;
    this()
    {
        root = new QObject;
    }
    ~this()
    {
        dispose(root);
    }
}

GC runs destructors in a dedicated thread. If the QObject participates in event dispatching, deleteLater method can be used to ensure that the object is deleted in the event loop of the thread the object is attached to. Note that threads stopped by the GC are resumed before the GC thread runs the destructors so there is no risk of deadlocks.

class C
{
    QObject root;
    this()
    {
        root = new QObject;
    }
    ~this()
    {
        root.deleteLater();
    }
}

DO NOT dispose the object if it is a child of the enclosing QObject:

class C : QObject
{
    QObject root;
    this()
    {
        root = new QObject(this);
    }
}
QObject root;
static this() {
    root = new QObject;
}
static ~this() {
    dispose(root);
}

Non-QObject classes

TBD

Object destruction order

One of the typical mistakes made by new QtD users may lead to a crash when a QtD application more complicated than Hello world closes. Consider the following example:

int main(string[] args)
{
    auto app = new QApplication(args);
    auto mainWin = new MainWindow;
    mainWin.show;

    return app.exec;
}

where MainWindow is our custom QMainWindow subclass, containing toolbars, menus, etc. Once we go out of main() scope GC performs a collection. The problem is that the order, in which CG finalizes objects is not defined and, in our example, it happens to call mainWin's destructor after app's destructor has been called. Qt requires that all GUI-related objects be destroyed before the instance of QApplication is destroyed. The requirement is not met and the application crashes. One possible way to enforce object destruction order is to use 'scope' storage class, which allocates objects on stack, constructs them in lexical order and destroys in the reverse order:

int main(string[] args)
{
    auto app = scoped!QApplication(args);
    auto mainWin = scoped!MainWindow();
    mainWin.show();

    return app.exec();
}

Structs

Note that destructors are currently not called on struct objects allocated on GC heap (http://d.puremagic.com/issues/show_bug.cgi?id=2834). This means that such objects (and arrays of such objects) should be manually destroyed with qtd.QtdObject.dispose. Also, the built-in append operator (~) and 'length' property setter should be avoided. We recommend to store struct objects in Qt containers rather than built-in arrays.