This is indeed one of the more confusing parts of Qt for someone coming from a traditional C++ background.What is the general thumb rule in Qt?
The rule of thumb is that "Anything created (using operator new() with a non-NULL parent object (QObject *, QWidget *) will be deleted when the parent is deleted." What this means in practice is:
- If you create QMainWindow on the stack (in main()), all of its children will be deleted when the program exits (so you don't need to worry about deleting any child window you create with your QMainWindow as its ancestor).
- Any time you add a child to another QObject, that transfers ownership and the child will be deleted when the QObject is
- This rule holds for both QWidget and non-QWidget (eg. QObject) hierarchies
- QObjects created on the stack are deleted (along with their children) when that part of the stack goes out of scope.
It is because of these parent-child ownership relationships that copy constructors and assignment operators are disabled for QObject-derived classes.
These same rules hold for objects in QGraphicsItem hierarchy, even though they are not QObject-based.
For QStandardItem, QTableWidgetItem, and similar classes that are not QObject-based, when you give them to an instance that *is* QObject-based, you transfer the ownership (and lifetime control) to that instance. This is why calling QStandardItemModel::appendRow() doesn't cause a memory leak.
Object instances that are designed to be shared (like QAbstractItemModel instances, for which a single instance can be shared by many views), these are usually QObject-based, and are constructed with a QObject instance as their parent. So in the code I posted earlier, the QStandardItemModel instance was created with the QMainWindow as its parent, and will be deleted along with the parent.
For GUI classes with a .ui file created in Designer, there are at least three conventions: 1) include a "ui" class pointer as a member variable, 2) multiply inherit the GUI class from both a QWidget parent and the UI class, or 3) include a ui class member variable (not a pointer to one).
In the first case, it is customary to initialize the ui pointer by calling operator new() and then ui->setupUi() in the GUI class constructor. The ui class instance has no "parent", and so it must be explicitly deleted in the GUI class destructor.
In the second and third cases, there is no operator new() involved, and the ui is initialized by calling either setupUi() (case 2) or ui.setupUi() (case 3).
Bookmarks