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


最簡單的寫法:

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

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

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

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

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

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

使用的時候直接這樣——

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

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

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

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

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

好評好評。

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

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

 

https://blog.yeatse.com/2015/03/03/qt-singleton-implementation/


免責聲明!

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



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