qt的單例模式-靜態成員變數的銷燬方法
阿新 • • 發佈:2018-12-25
最近程式設計學習了一下基礎知識,順便隨手記錄下,文章涉及的部分內容均已標明出處。
文中涉及到的知識點如下:
- 單例模式
- 靜態指標的記憶體釋放
- 類中宣告子類的宣告與實現方法
- Qt的main函式正確的編寫格式(記錄此坑)
.h–介面檔案
class MainWindow : public QMainWindow { Q_OBJECT static MainWindow *m_pselfmainwin; class Garber //垃圾自動回收--目的使m_pselfmainwin自動析構 { public: Garber(); ~Garber(); }; static Garber garbor; MainWindow(QWidget *parent = NULL); ~MainWindow(); public: static MainWindow * getInstance(); }
.cpp實現檔案
//靜態成員類外初始化 MainWindow * MainWindow::m_pselfmainwin = NULL; //巢狀類的靜態成員類外初始化 MainWindow::Garber MainWindow::garbor = MainWindow::Garber() ; MainWindow::Garber::Garber() // { }; MainWindow::Garber::~Garber() //刪除靜態成員變數 { if (m_pselfmainwin!=NULL) { delete m_pselfmainwin ; m_pselfmainwin = NULL; } }; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { } MainWindow::~MainWindow() { } MainWindow * MainWindow::getInstance() { if (m_pselfmainwin==NULL) { //m_pselfmainwin = new MainWindow(); //智慧指標 QScopedPointer<MainWindow> m_pselfmainwin(new MainWindow); m_pselfmainwin->setAttribute(Qt::WA_DeleteOnClose); m_pselfmainwin->initHmi(); } return m_pselfmainwin; }
main.cpp實現檔案
int main(int argc ,char *argc[])
{
QScopedPointer<QApplication> app(new QApplication(argc, argv));
MainWindow *pmainWindow = MainWindow::getInstance();// 單例模式獲取例項
pmainWindow->show();
return app->exec();
}
至此單例模式的靜態指標銷燬實現完畢!
題外話:
1.垃圾回收參看如下連結:
https://blog.csdn.net/roy1261/article/details/51425987
2.由於使用的是qt4.7.3版本的原因,在手動關閉MainWindow 視窗時出現記憶體訪問錯誤的資訊,原因是引用原文如下:
參看連線 https://www.devbean.net/2012/08/qt-study-road-2-hello-world/
首先,按照標準 C++ 來看這段程式。這裡存在著記憶體洩露。當exec()退出時(也就是事件迴圈結束的時候。視窗關閉,事件迴圈就會結束),label 是沒辦法 delete 的。這就造成了記憶體洩露。當然,由於程式結束,作業系統會負責回收記憶體,所以這個問題不會很嚴重。即便你這樣修改了程式碼再執行,也不會有任何錯誤。
早期版本的 Qt 可能會有問題(詳見本文最後帶有刪除線的部分,不過豆子也沒有測試,只是看到有文章這樣介紹),不過在新版本的 Qt 基本不存在問題。在新版本的 Qt 中,app.exec()的實現機制確定,當最後一個可視元件關閉之後,主事件迴圈(也就是app.exec())才會退出,main()函式結束(此時會銷燬app)。**這意味著,所有可視元素已經都關閉了,也就不存在後文提到的,QPaintDevice沒有QApplication例項這種情況。**另外,如果你是顯式關閉了QApplication例項,例如呼叫了qApp->quit()之類的函式,QApplication的最後一個動作將會是關閉所有視窗。所以,即便在這種情況下,也不會出現類這種問題。
由於是在main()函式中,當main()函式結束時,作業系統會回收程序所佔用的資源,相當於沒有記憶體洩露。不過,這裡有一個潛在的問題:作業系統只會粗暴地釋放掉所佔記憶體,並不會呼叫物件的解構函式(這與呼叫delete運算子是不同的),所以,很有可能有些資源佔用不會被“正確”釋放。事實上,在最新版的 Sailfish OS 上面就有這樣的程式碼:
#include <QApplication>
int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(new QApplication(argc, argv));
QScopedPointer<QQuickView> view(new QQuickView);
view->setSource("/path/to/main.qml");
...
return app->exec();
}