一 說明
在qt代碼中,我們經常給類的構造函數傳入父指針,這個有什麼用?類執行個體化後又是在什麼時候釋放的?
為了避免代碼運作中出現記憶體洩漏,規範程式設計習慣,下面做一個驗證。
其次也是對qt中對象樹做一些了解,qt對象樹學習文章:https://zhuanlan.zhihu.com/p/43523879
對象樹在 GUI 程式設計中是非常非常有用的!當父對象被析構時子對象也會被析構,這樣一定程度上簡化了記憶體回收機制。
二 測試類設計
使用定時器列印資訊,這樣表示類執行個體化後是否被釋放。
h檔案
#ifndef TESTCLASS_H
#define TESTCLASS_H
#include <QObject>
#include <QTimer>
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = nullptr,QString info = "");
signals:
public slots:
private:
QString myInfo;
};
#endif // TESTCLASS_H
cpp檔案
#include "testclass.h"
#include <qDebug>
TestClass::TestClass(QObject *parent,QString info) :
QObject(parent),
myInfo(info)
{
QTimer *time = new QTimer(this);
connect(time,&QTimer::timeout,this,[=](){
qDebug()<<Q_FUNC_INFO<<myInfo;
});
time->start(1000);
}
三 測試代碼設計
使用mainwindows中加入一個按鈕,使用按鈕控制From類的建立與釋放,然後再From類中使用各種方式建立TestClass類。
1 mainwindow類設計
h檔案
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "form.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
Form *win;
};
#endif // MAINWINDOW_H
cpp檔案
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
win = NULL;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
if(win != NULL)
{
delete win;
win = NULL;
}
else
{
win = new Form();
win->show();
}
}
3 From類測試的實作
h檔案
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include "testclass.h"
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = 0);
~Form();
private:
Ui::Form *ui;
TestClass c;
};
#endif // FORM_H
cpp檔案
#include "form.h"
#include "ui_form.h"
Form::Form(QWidget *parent) :
QWidget(parent),
ui(new Ui::Form),
c(NULL,"C") //設定父對象無效,this對象釋放的時候,c依據被釋放
{
ui->setupUi(this);
TestClass *a = new TestClass(this,"A"); //等this對象(From)釋放時釋放
TestClass *b = new TestClass(nullptr,"B"); //需要等程序關閉後,系統自動回收
TestClass *e = new TestClass(parent,"E"); //需要等parent對象(Mainwindow)釋放時釋放
}
Form::~Form()
{
delete ui;
}
3 測試結論
- new執行個體化,傳入父類指針,随着父類指針釋放的時候釋放,子類前于父類執行析構函數。
- new執行個體化,傳入父指針為空,即無父對象時,需要手動釋放,即使用delete(一般放在析構函數中),否則需要等待程序關閉後系統回收(此情況為記憶體洩漏)。
- 類成員子類,執行個體化在構造的時候,釋放的方式無法通過修改父對象修改,即使後期将父對象改為空。如:在From釋放的時候,From的成員子類c,雖然後面改了c的父對象,在From對象釋放的時候,c依據被釋放。 原因分析: c作為成員,c的記憶體段在From記憶體範圍内,在From釋放後,其所有記憶體都要被釋放,是以c也一定會被釋放。
在From類代碼的注釋中也有展現,如果有興趣的可以使用代碼跑一下體驗體驗。