The Qt Doc says if a QObject has a parent, then when the parent is deleted, it will also delete all its children. However, if I have multiple QObjects with the default parent (0), when will they be deleted? And what will be the sequence of deleting?
1 Answers
If we're talking about pointers to QObject
, no, they won't be deleted. You will have a memory leak unless you delete them manually so there won't be any sequence of deleting.
Pointers don't release their memory unless delete
is called on them. Say you have a pointer to a memory location to which no other pointer points. If that pointer goes out of scope and you don't call delete on it, you will have a memory leak because if no other pointer points to that memory location then you won't have access to that memory location anymore. And you get an inaccessible and useless chunk of memory.
In classes, destructors have the purpose of releasing the memory when deleted. Destructors are called when instances of the classes go out of scope(in case of instances allocated on the stack i.e. static, e.g. MyClass x;
) or when delete is called of them(in case of pointers i.e. dynamic, e.g. MyClass *x = new MyClass;
)
Qt
created a clever mechanism so that programmers won't have to think that much of these things because lots of errors occur because of them. So Qt
introduced parents, i.e. if you set a QObject
a parent, when you will delete the parent the QObject
will be deleted as well.
If you use QObject
pointers as members in a class and don't set them a parent, when an instance of that class gets deleted you will have a memory leak unless, of course, you delete them manually in the destructor.
For example the following implementation will create memory leak if used:
class MyObject : public QObject
{
public:
MyObject(QObject *parent = 0);
~MyObject();
private:
QTimer *m_pTimer;
}
MyObject::MyObject(QObject *parent) : QObject(parent)
{
m_pTimer = new QTimer; // memory leak when this will be destroyed
}
MyObject::~MyObject()
{
}
In order to fix this you should provide this
as parent:
MyObject::MyObject(QObject *parent) : QObject(parent)
{
m_pTimer = new QTimer(this);
}
or
MyObject::~MyObject()
{
delete m_pTimer;
}
In an implementation like this:
class MyObject : public QObject
{
public:
MyObject(QObject *parent = 0);
~MyObject();
private:
QTimer m_timer;
}
MyObject::MyObject(QObject *parent) : QObject(parent)
{
// Do stuff
}
MyObject::~MyObject()
{
}
where you don't have pointers and memory allocated on the heap, all the members are destroyed when getting out of scope i.e. when the instance of the class(in our case MyObject
) gets out of scope.
I consider worth mentioning here the layouts system in Qt
.
Lets say you have a QWidget
with a QPushButton
inside it. If you create a QLayout
, add the QPushButton to the QLayout
and set the QLayout
on the QWidget
with QWidget::setLayout
, automatically a child-parent relationship will be created between the QPushButton
and the QWidget
and also between the QLayout
and the QWidget
.
Here's an example:
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private:
QGridLayout *m_pLayout;
QPushButton *m_pButton;
};
Widget::Widget(QWidget *parent) :
QWidget(parent)
{
m_pLayout = new QGridLayout;
m_pButton = new QPushButton;
m_pButton->setText("Push me!");
m_pLayout->addWidget(m_pButton, 0, 0);
setLayout(m_pLayout); // In this moment *this* will be automatically
// set as parent for both m_pLayout and m_pButton
// even though no parent was passed to their constructors.
}
Widget::~Widget()
{
}
I hope this helps.
-
1You have an empty destructor in your example where you use `new QTimer`. You state *In order to fix this you should provide this as parent:* `code snippet` *or* `empty desctructor`. I think you wanted to put `delete timer;` there. – thuga Oct 22 '14 at 06:18