目的
本例簡介C++中單例模式的最優寫法,
實作
基礎寫法
下面的代碼是C++單例的基礎寫法,在靜態函式Singleton::getInstance()中定義了Singleton的靜態變數物件,并回傳此物件的參考,
由于C++函式的靜態變數唯一性,可以確保例子中s物件的唯一性,執行緒同步,以及靜態物件間的依賴關系等問題,
#include <iostream>
class Singleton {
public: static Singleton &getInstance() {
static Singleton s;
return s;
}
public: void test() {
std::cout << "test" << std::endl;
}
};
int main() {
Singleton &s = Singleton::getInstance();
s.test();
return 0;
}
完整寫法
如果對代碼要求比較嚴格,可以把該關閉的函式都關掉,這取決與你:):
- 建構式私有化,使得外部無法創建Singleton物件,
- 關閉拷貝建構式,右值拷貝建構式,
- 關閉賦值運算子多載函式,
class Singleton {
private: Singleton() { }
Singleton(const Singleton &) = delete;
Singleton(const Singleton &&) = delete;
Singleton &operator=(const Singleton &) = delete;
public: static Singleton &getInstance() {
static Singleton s;
return s;
}
public: void test() {
std::cout << "test" << std::endl;
}
};
對比
New
使用下面方法的也比較多,缺點是在無法保證getInstance()的執行緒安全性,如果工程比較大,會存在多個執行緒同時呼叫Singleton::getInstance()方法導致創建多實體的問題,
class Singleton {
private: static Singleton *instance;
public: static Singleton *getInstance() {
if (NULL == instance)
instance = new Singleton();
return instance;
}
};
Lock
所以可能會加一堆lock, 為了性能還寫個double check, 比如下面這樣,寫起來比較麻煩,個人不太喜歡,
class Singleton {
private: static Singleton *instance;
public: static Singleton *getInstance() {
if (NULL == instance) {
// TODO LOCK
if (NULL == instance)
instance = new Singleton();
}
return instance;
}
};
靜態成員
如果把函式內的靜態變數變成類的靜態成員變數呢?簡單的工程行,復雜的不行,因為如果靜態類之間有依賴,可能會導致C++的一些未定義的行為,
- 下例中的Singleton::instance 保存在程式全域的靜態資料區,instance初始化的時機是在程式的main()函式執行前,
- 假設有SingletonB::instance,與Singleton::instance類似定義,也是靜態類成員變數,SingletonB::instance和Singleton::instance的初始化順序是未定義的,得看編譯器的心情,
- 如果Singleton::instance 的初始化在SingletonB::instance之前,而Singleton的建構式中恰好需要參考到SIngleonB::instance,就很可能會出現一些未定義的行為,
#include <iostream>
class Singleton {
private: static Singleton instance;
public: static Singleton &getInstance() {
return instance;
}
public: void test() {
std::cout << "test" << std::endl;
}
};
Singleton Singleton::instance;
int main() {
Singleton &s = Singleton::getInstance();
s.test();
return 0;
}
總結
- 如果專案小,建議上述單例中的簡單寫法就夠了,
- 如果專案大,可以寫全點兒,
參考
[1] Efficitive C++
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/231991.html
標籤:其他
上一篇:Java多執行緒技術概述
