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

Nya*_*uko 2 qt qobject

Qt Doc说如果QObject有父对象,那么当父对象被删除时,它也会删除它的所有子对象.但是,如果我有多个具有默认父级(0)的QObject,它们什么时候会被删除?那删除的顺序是什么?

Iul*_*liu 5

如果我们正在谈论指针QObject,不,它们将不会被删除.除非您手动删除它们,否则将发生内存泄漏,因此不会有任何删除序列.

指针除非delete被调用,否则不释放内存.假设您有一个指向没有其他指针指向的内存位置的指针.如果该指针超出范围并且您没有在其上调用delete,则会出现内存泄漏,因为如果没有其他指针指向该内存位置,则您将无法再访问该内存位置.而且你会得到一个无法访问和无用的内存块.

在类中,析构函数的目的是在删除时释放内存.析构函数被调用时的类的实例走出去的范围(在栈上分配的情况下的情况下,静态的,例如 MyClass x;),或删除时,称他们的(在三分球的情况下,即动态, 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()
{
}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,你应该提供this父母:

MyObject::MyObject(QObject *parent) : QObject(parent)
{
    m_pTimer = new QTimer(this);
}
Run Code Online (Sandbox Code Playgroud)

要么

MyObject::~MyObject()
{
    delete m_pTimer;
}
Run Code Online (Sandbox Code Playgroud)

在这样的实现中:

class MyObject : public QObject
{
public:
    MyObject(QObject *parent = 0);
    ~MyObject();

private:
    QTimer m_timer;
}

MyObject::MyObject(QObject *parent) : QObject(parent)
{
    // Do stuff
}

MyObject::~MyObject()
{
}
Run Code Online (Sandbox Code Playgroud)

如果你没有在堆上分配指针和内存,那么当超出范围时,当类的实例(在我们的例子中MyObject)超出范围时,所有成员都会被销毁.

我认为这里值得一提的布局系统Qt.

让我们说你有QWidget一个QPushButton内部.如果你创建QLayout,添加QPushButton到QLayout并设置QLayoutQWidgetQWidget::setLayout自动了父子关系之间创建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()
{
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.