Qt中具有默认父对象的QObject的删除序列是什么?

3
Qt文档指出,如果一个QObject有父对象,那么当父对象被删除时,它也将删除所有的子对象。然而,如果我有多个默认父对象(0)的QObjects,它们何时会被删除?并且删除的顺序是什么?
1个回答

7
如果我们谈论指向QObject的指针,那么不,它们不会被删除。除非您手动删除它们,否则会有内存泄漏,因此不会有任何删除序列。
指针不释放它们的内存,除非对它们调用delete。假设您有一个指针指向一个没有其他指针指向的内存位置。如果该指针超出范围并且您没有调用delete,则会导致内存泄漏,因为如果没有其他指针指向该内存位置,则您将无法再访问该内存位置。然后您得到一块无法访问和无用的内存。
在类中,析构函数的目的是在删除时释放内存。当类的实例超出范围(在堆栈上分配实例的情况下,即静态,例如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中的布局系统
假设你有一个包含QPushButtonQWidget。如果你创建一个QLayout,将QPushButton添加到QLayout并使用QWidget::setLayout设置QLayout,那么QPushButtonQWidget之间以及QLayoutQWidget之间将自动创建子父关系。
以下是一个示例:
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()
{
}

我希望这有所帮助。

1
你的示例中有一个空的析构函数,其中你使用了new QTimer。你说为了修复这个问题,你应该提供它作为父对象: 代码片段 或者 空的析构函数。我认为你想在那里放置delete timer; - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接