對單例模式的一個簡單思考

測試代碼以下: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對象吧,最終的結果和我料想的有所不一樣:測試

image

只構造出了參數爲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了。

相關文章
相關標籤/搜索