Qt - 内存回收机制
1. 内存回收机制
Qt中有内存回收机制, 但是不是所有被new出的对象被自动回收, 满足条件才可以回收
如果想要在Qt中实现内存的自动回收, 需要满足以下两个条件:
- 创建的对象必须是QObject类的子类(间接子类也可以)
- 创建出的类对象, 必须要指定其父对象是谁, 一般情况下有两种操作方式
对于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;
}
关闭主窗口: