目錄html
在C++中學習過程當中,咱們都知道:app
Qt做爲C++的庫,顯然是不會違背C++的前述原則的。但是:函數
注:本文暫不涉及智能指針(smart pointer)相關的東西,你能夠考慮 Qt 智能指針學習 一文post
在Qt中,如下狀況下你new出的對象你能夠不用 親自去delete (但你應該清楚delete在何處被Qt調用的,怎麼被調用的):學習
除此以外,有些類的對象能夠接收設置一些特別的標記,好比:ui
注意:這些用法會有些陷阱 ,請注意看本文最後的3個小例子。this
在Qt中,最基礎和核心的類是:QObject 。它的魔力很大,本文只關注兩點:spa
在Qt中,每一個 QObject 內部都有一個list,用來保存全部的 children,還有一個指針,保存本身的parent。當它本身析構時,它會將本身從parent的列表中刪除,而且析構掉全部的children。.net
Q_INVOKABLE QObject::QObject ( QObject * parent = 0 )
QObject::~QObject () [virtual]
void QObject::setParent ( QObject * parent )
注:這三個函數都是經過一個內部私有函數來實現的,這就是指針
QObjectPrivate::setParent_helper(QObject *o)
每一個QObject只有一個父對象:
QObject * QObject::parent () const
子對象能夠有多個
const QObjectList & QObject::children () const
因此能夠根據條件來查找嘍:
T QObject::findChild ( const QString & name = QString() ) const QList<T> QObject::findChildren ( const QString & name = QString() ) const
deleteLater 包含兩層意思了
呵呵,彷佛這是廢話哈。
在去年春節前的時候吧,有人對
obj-> deleteLater()
會像下面同樣調用delete:
delete obj;//注:等同
感到不解。而後我寫了這樣一個C++例子:
class A { public: A(){} void deleteMe() { delete this; } }; int main() { A * a = new A; a->deleteMe(); return 0; }
應該不須要解釋吧
Qt 是事件驅動的,因此發送一個刪除事件到事件系統就能夠啦:
void QObject::deleteLater() { QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete)); }
事件循環稍後看到該事件就會將其派發會這個widget:
bool QObject::event(QEvent *e) { switch (e->type()) { ... case QEvent::DeferredDelete: ...
很簡短、很熟悉的一個例子是不?可是 若是你發現對象的析構函數始終不被成功調用 ,會有什麼感受?
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel *label = new QLabel("Hello Qt!"); label->show(); return app.exec(); }
這是 C++ GUI Programming with Qt 4 一書的第一個例子。咱們注意到這兒的 label 既沒有指定parent,也沒有對其調用delete。
因此,這兒會形成內存泄露。
書中解釋說,對於這種小例子,這點內存泄露不算什麼。不清楚官方這個例子的意圖是什麼,或許是一開始就讓你們用指針吧。
三種改進方式
QLabel label("Hello Qt!"); label.show();
label->setAttribute(Qt::WA_DeleteOnClose);
int ret = app.exec(); delete label;
label=NULL; return ret;
強化一下對前一個例子的瞭解
#include <QApplication> #include <QLabel> int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label("Hello Qt!"); label.show(); label.setAttribute(Qt::WA_DeleteOnClose); return app.exec(); }
運行正常,退出時會崩潰 ,由於label被close時,將會 delete 這兒label對象,但label對象卻不是經過new分配到heap中的。
爲了使得用戶減小本身顯式使用delete,Qt將delete隱藏的比較深。這樣一來,不使用new爲對象分配空間時,反倒須要多多當心了。
看個小例子:這個程序退出時會直接崩潰 。
#include <QtGui> int main(int argc, char* argv[]) { QApplication app(argc, argv); QLabel label(tr"Hello Qt!"); QWidget w; label.setParent(&w); w.show(); return app.exec(); }
QLabel label(); delete &label;
QLabel *label = new QLabel("Hello Qt!"); label.setParent(&w)
QWidget w; QLabel label(tr"Hello Qt!");
Qt 對象的父子關係的引入,簡化了咱們對內存的管理,可是,因爲它會在你不太注意的地方調用 delete,因此,使用時仍是要小心。
轉自:http://blog.csdn.net/dbzhang800/article/details/6300025