測試代碼以下:ios
#include <iostream> class TestSingleton { public: ~TestSingleton() { std::cout << "TestSingleton " << m_i << " destructor\n"; } static TestSingleton& getInstance(int i) { static TestSingleton ts(i); return ts; } private: TestSingleton(int i):m_i(i) { std::cout << "TestSingleton " << m_i << " constructor\n"; } int m_i; }; int main() { TestSingleton& ts1 = TestSingleton::getInstance(1); TestSingleton& ts2 = TestSingleton::getInstance(2); }
代碼很簡單,最終的結果怎樣呢?函數
我本來覺得1和2都會輸出的,由於兩次分別調用getInstance時用的是不同的參數,因此應該會實例出兩個不同的TestSingleton對象吧,最終的結果和我料想的有所不一樣:測試
只構造出了參數爲1的singleton對象,並沒與改造出參數爲2的對象,這是爲何呢?仔細思考了一下,而後就頓悟了,哎,緣由仍是出了對static關鍵字的理解不深,這麼快就忘記了。spa
在函數體中,若是聲明瞭一個static變量,無論進入這個函數多少次,該static變量只會被初始化一次。設計
因此當我第二次調用getInstance函數時,進入getInstance後直接就跳過了TestSingleton的初始化語句,也就是TestSingleton的構造函數,所以最終獲得的TestSinglon對象和上次的是同一個。我打斷點調試的時候發現確實如此。調試
從這裏我收穫了一個小小的道理,單例模式的構造函數不該該傳參,若是須要傳參的話,這個類就應該被設計爲普通類。由於若是須要傳參的話,就很根據不一樣的參數生成不一樣的類的實例,與單例類「一個類只存在一個對象」的設定不符。code
其實道理與下面這個是類似的。對象
void fun(int i) { static int m(i); std::cout << m << "\n"; } int main() { fun(1); fun(2); }
最終兩次的輸出結果依然都是1,由於m只被初始化一次。blog
void fun(int i) { static int m = i; std::cout << m << "\n"; } int main() { fun(1); fun(2); }
最終的輸出仍然爲兩個1,這段和上段代碼有點相似於 類的拷貝構造和賦值構造 都是」構造函數」。get
void fun(int i) { static int m; m = i; std::cout << m << "\n"; } int main() { fun(1); fun(2); }
這樣的話輸出結果就變成一個1和一個2了。