天天看點

Qt中的“析構”機制、QObject *parent、注意事項

在C++中,使用new在堆中建立的對象,需要使用delete來析構對象,進而釋放堆中的記憶體的。

在Qt中,往往new出來的對象卻不需要我們手動delete,這是因為Qt替我們做了delete這件事。

QObject *parent,有時候是QWidget *parent:

在很多時候,我們建立一個對象(無論是直接建立,還是new出來一個),都需要傳入一個“parent”指針或者手動調用setParent(*parent)函數來指定一個“父視窗”,預設的parent指針是空,此時的“父視窗”為目前的作業系統。

當指定了“父視窗”之後,該視窗的析構就由父視窗來接管,Qt會保證在合适的時候析構該視窗,并且隻析構一次。這是一個很優秀的機制。

說明:

堆對象/new出來的對象:

①QObject *parent/QWidget *parent,當指定了parent後,Qt就會介入,在合适的時候調用對應的delete操作。

②在不指定parent時,最好手動設計delete,否則這個對象的記憶體空間将交給作業系統來管理,通常在整個程式關閉以後,作業系統會回收該記憶體,一般也不會造成問題,但這畢竟是一個潛在的危險,有隐患。

棧對象:

③棧是“先入後出,後入先出”的方式,是以在建立棧對象的時候,要注意順序,舉一個例子說明:

a>出錯例子:

#include <QtGui/QApplication>      
#include <QWidget>      
#include <QPushButton>      
int main(int argc, char *argv[])      
{      
QApplication a(argc, argv);      
QPushButton btn;//先建立QPushButton      
QWidget w;//後建立QWidget      
w.show();      
btn.setText("Helloworld");      
btn.setParent(&w);//傳入了w作為父視窗      
btn.show();      
return a.exec();      
}      
Qt中的“析構”機制、QObject *parent、注意事項
Qt中的“析構”機制、QObject *parent、注意事項

在點選了“關閉”之後,程式崩潰了,原因是:因為btn指定了父視窗w,在關閉w時,Qt的析構機制的做法是先析構btn再析構w;在建立對象的時候,btn先建立w後建立,在棧的“先入後出,後入先出”方式下,w先出棧,btn後出棧,而此時btn已經在前面出棧了(Qt的析構機制),導緻現在程式崩潰。

b>改正後

#include <QtGui/QApplication>      
#include <QWidget>      
#include <QPushButton>      
int main(int argc, char *argv[])      
{      
QApplication a(argc, argv);      
QWidget w;      
w.show();      
QPushButton btn;//将QPushButton的建立放在QWidget之後      
btn.setText("Helloworld");      
btn.setParent(&w);      
btn.show();      
return a.exec();      
}      

這樣做,在點選“關閉”時,便先會将btn出棧,Qt的析構機制檢測到btn已出棧,便不會再進行析構了。