So why does Documentation says that order of destruction doesn't matter?
It means that you don't NEED to delete objects manually. Qt will register object within parent/child hierarchy and kill it when necessary.
Of course, it can't track all pointers you might have stored somewhere. So if you take a pointer to object, then delete object's parent, then attempt to delete pointer you took, that'll be entirely your fault.
Should we be always careful about deleting child object?
No. When you delete child object it will unregister itself from its parent.
If you delete second
, then delete first
, program will work fine.
So you should remember that once you killed an object all its children are gone.
By the way, Qt has QPointer
class made specifically for this situation, so you should use it instead of raw pointers. QPointer
will set itself to zero when object it points to is destroyed.
But if I delete it causes segmentation fault.
It means that your program has a bug you haven't fixed. And most likely (98% possibility) the bug is within your code, and is not Qt's fault. Debug the segfault and see where it happens.
explanation
QWidget* first = new QWidget;
QWidget* second = new QWidget(first);
delete first;
delete second;
When you delete first
it also deletes second
, because second
is its child.
However, your pointer second
will not be automatically updated. It'll turn into dangling pointer (points at object that is no longer there), and attempt to delete it, will trigger undefined behavior, which, in your case, will crash the program.
If you INSIST on keeping separate pointer for second
AND deleting second
after first
(again), you can use something like this (don't forget to #include <QPointer>
):
QPointer<QWidget> first = new QWidget,
second = new QWidget(first);
delete first;
delete second;
However, there's no real need for that, and normally people simply do this:
QWidget *first = new QWidget,
*second = new QWidget(first);
delete first;//second is deleted automatically
Normally, in C++ you have to delete
every object you allocated (with new
) yourself, manually. This is error-prone, requires you to write a destructor, and you might somemetimes forget about it, which will result in memory leak.
However, QObject automatically deletes all its children within its destructor, which means it is perfectly okay to do this:
QObject *a = new QObject();
QObject *b = new QObject(a);
b = new QObject(a);
b = new QObject(a);
As long as you remember to delete top-level object, all its child resources will be automatically freed.
However, Qt cannot track pointers you stored. So if you do something like this:
QObject *a = new QObject(), *b = a;
delete a;
It will not update existing raw pointers. That's standard C++ behavior, by the way.
That's what QPointers are for:
QObject *a = new QObject(), *b = a;
QPointer<QObject> c = a;
delete a;
//at this point c is set to zero. a and b still point at previous object locations.