1. 程式人生 > >qt的單例模式-靜態成員變數的銷燬方法

qt的單例模式-靜態成員變數的銷燬方法

最近程式設計學習了一下基礎知識,順便隨手記錄下,文章涉及的部分內容均已標明出處。
文中涉及到的知識點如下:

  1. 單例模式
  2. 靜態指標的記憶體釋放
  3. 類中宣告子類的宣告與實現方法
  4. 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();
}