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

最簡單的寫法:c++

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();
}

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

惋惜每次都要重複這麼幾行實在麻煩,因而寫了一個模板類:spa

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(); \
}

而後聲明的時候,填加一行這個宏:code

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

好評好評。對象

固然,爲了要保證真的是單例模式,還要把構造函數限制爲private,否則之後何時忘記了這碼事,在外面又new了一下就很差了。blog

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

 

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

相關文章
相關標籤/搜索