Qt 單例模式的實現(4種方法)


最簡單的寫法:

1 static MyClass* MyClass::Instance() 2 { 3     static MyClass inst; 4     return &inst; 5 }

過去很長一段時間一直都這么寫,簡單粗暴有效。但是直接聲明靜態對象會使編譯出的可執行文件增大,也有可能出現其他的一些問題,所以利用了Qt自帶的智能指針QScopedPointer和線程鎖QMutex,改成了需要時才動態初始化的模式:

 1 static MyClass* MyClass::Instance()  2 {  3     static QMutex mutex;  4     static QScopedPointer<MyClass> inst;  5     if (Q_UNLIKELY(!inst)) {  6         mutex.lock();  7         if (!inst) {  8             inst.reset(new MyClass);  9  } 10  mutex.unlock(); 11  } 12     return inst.data(); 13 }

既保證了線程安全又防止了內存泄漏,效率也沒降低太多,簡直完美。

可惜每次都要重復這么幾行實在麻煩,於是寫了一個模板類:

 1 template <class T>
 2 class Singleton  3 {  4 public:  5     static T* Instance()  6  {  7         static QMutex mutex;  8         static QScopedPointer<T> inst;  9         if (Q_UNLIKELY(!inst)) { 10             mutex.lock(); 11             if (!inst) { 12                 inst.reset(new T); 13  } 14  mutex.unlock(); 15  } 16         return inst.data(); 17  } 18 };

使用的時候直接這樣——

MyClass* inst = Singleton<MyClass>::Instance();

除了用模板類,還可以利用c++中強大的宏:

 1 #define DECLARE_SINGLETON(Class) \
 2 Q_DISABLE_COPY(Class) \  3 public: \  4     static Class* Instance() \  5  { \  6         static QMutex mutex; \  7         static QScopedPointer<Class> inst; \  8         if (Q_UNLIKELY(!inst)) { \  9             mutex.lock(); \ 10             if (!inst) inst.reset(new Class); \ 11  mutex.unlock(); \ 12  } \ 13         return inst.data(); \ 14     }

然后聲明的時候,填加一行這個宏:

1 class MyClass 2 { 3     DECLARE_SINGLETON(MyClass);    // 聲明單例模式 4     //...
5 }

好評好評。

當然,為了要保證真的是單例模式,還要把構造函數限制為private,不然以后什么時候忘記了這碼事,在外面又new了一下就不好了。

另外Qt本身自帶了一個宏Q_GLOBAL_STATIC,也有類似單例模式的效果,QThreadPool::globalInstance()函數的實現就是利用了這個宏。不過它的主要用處是聲明全局變量,和Singleton還是有差別的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM