Qt - 内存回收机制

1. 内存回收机制

Qt中有内存回收机制, 但是不是所有被new出的对象被自动回收, 满足条件才可以回收

如果想要在Qt中实现内存的自动回收, 需要满足以下两个条件:

  1. 创建的对象必须是QObject类的子类(间接子类也可以)
  2. 创建出的类对象, 必须要指定其父对象是谁, 一般情况下有两种操作方式

对于1:

QObject类是没有父类的, Qt中有很大一部分类都是从这个类派生出去的

Qt中使用频率很高的窗口类和控件都是 QObject 的直接或间接的子类

对于2:

// 方式1: 通过构造函数
// parent: 当前窗口的父对象, 找构造函数中的 parent 参数即可
QWidget::QWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
QTimer::QTimer(QObject *parent = nullptr);

// 方式2: 通过setParent()方法
// 假设这个控件没有在构造的时候指定符对象, 可以调用QWidget的api指定父窗口对象
void QWidget::setParent(QWidget *parent);
void QObject::setParent(QObject *parent);

对于窗口类,QWidget是所有类的父类,使用QWidget *parent 父类指针指向子类对象

对于其他类,QObject 是所有类的父类,使用QObject *parent父类指针指向子类对象

主要就是这两种父类指针,父类指针创建的目的很大程度上就是为了资源回收。

当父对象析构的时候,先把所有的子对象析构,最后在析构父对象。

 

2. 内存回收本质

当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。当父对象析构的时候,这个列表中的所有对象也会被析构。

任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。

当父对象析构的时候,先把所有的子对象析构,最后在析构父对象。

 

3. 测试代码

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "subwindows.h"
#include "mybutton.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    SubWindows* subwin = new SubWindows(this);
    subwin->show();

    MyButton* btn = new MyButton(subwin,"我的按钮");
    btn->show();
}

MainWindow::~MainWindow()
{
    delete ui;
    qDebug()<<"MainWindow的析构函数"<<endl;
}

mybutton.h

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QPushButton>

class MyButton: public QPushButton
{
public:
    MyButton(QWidget *parent = 0,QString text ="");
    ~MyButton();
};

#endif // MYBUTTON_H

mybutton.cpp

#include "mybutton.h"
#include <QDebug>


MyButton::MyButton(QWidget *parent,QString text):QPushButton(parent)
{
    this->setFixedSize(80,30);
    this->setText(text);
}

MyButton::~MyButton()
{
    qDebug()<<"MyButton的析构函数";
}

subwindows.h

#ifndef SUBWINDOWS_H
#define SUBWINDOWS_H

#include <QDialog>

namespace Ui {
class SubWindows;
}

class SubWindows : public QDialog
{
    Q_OBJECT

public:
    explicit SubWindows(QWidget *parent = 0);
    ~SubWindows();

private:
    Ui::SubWindows *ui;
};

#endif // SUBWINDOWS_H

subwindows.cpp

#include "subwindows.h"
#include "ui_subwindows.h"
#include <QDebug>

SubWindows::SubWindows(QWidget *parent) :QDialog(parent),ui(new Ui::SubWindows)
{
    ui->setupUi(this);
}

SubWindows::~SubWindows()
{
    delete ui;
    qDebug()<<"subwindows的析构函数"<<endl;
}

关闭主窗口:

 

posted @ 2022-04-15 10:51  [BORUTO]  阅读(118)  评论(0编辑  收藏  举报