Qt Doc说如果QObject有父,那么当删除父对象时,它也会删除它的所有子对象。 但是,如果我有多个具有默认父级(0)的QObject,它们什么时候会被删除? 那删除的顺序是什么?
答案 0 :(得分:5)
如果我们正在谈论指向QObject
的指针,不会,它们将不会被删除。除非您手动删除它们,否则将会发生内存泄漏,因此不会有任何删除序列。
除非调用delete
,否则指针不会释放内存。假设您有一个指向没有其他指针指向的内存位置的指针。如果该指针超出范围并且您没有在其上调用delete,那么您将拥有memory leak,因为如果没有其他指针指向该内存位置,那么您将无法再访问该内存位置。而且你得到了一块无法访问和无用的内存。
在类中,析构函数的目的是在删除时释放内存。当类的实例超出范围时(如果在堆栈上分配实例,静态,例如 MyClass x;
)或者在调用delete时调用析构函数他们(如果指针即动态,例如 MyClass *x = new MyClass;
)
Qt
创建了一个聪明的机制,以便程序员不必考虑这些事情,因为很多错误都是因为它们而发生的。因此Qt
引入了父母,即如果您设置了QObject
父母,当您删除父母时,QObject
也会被删除。
如果您使用QObject
指针作为类中的成员而不将它们设置为父类,则当该类的实例被删除时,您将遇到内存泄漏,当然,除非您手动删除它们析构函数。
例如,如果使用以下实现将创建内存泄漏:
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()
{
}
为了解决此问题,您应该提供this
作为父级:
MyObject::MyObject(QObject *parent) : QObject(parent)
{
m_pTimer = new QTimer(this);
}
或
MyObject::~MyObject()
{
delete m_pTimer;
}
在这样的实现中:
class MyObject : public QObject
{
public:
MyObject(QObject *parent = 0);
~MyObject();
private:
QTimer m_timer;
}
MyObject::MyObject(QObject *parent) : QObject(parent)
{
// Do stuff
}
MyObject::~MyObject()
{
}
如果你没有在堆上分配指针和内存,那么当在类的实例(在我们的例子中MyObject
中超出范围即时,所有成员都会被销毁)超出范围。
我认为值得一提的是Qt
中的layouts system。
假设您的QWidget
内有QPushButton
。如果您创建QLayout
,请将QPushButton添加到QLayout
,并将QLayout
设置为QWidget
QWidget::setLayout
,自动建立子父关系在QPushButton
和QWidget
之间以及QLayout
和QWidget
之间创建。
以下是一个例子:
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()
{
}
我希望这会有所帮助。