对单例模式的一个简单思考

测试代码如下:

#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关键字的理解不深,这么快就忘记了。

在函数体中,如果声明了一个static变量,不管进入这个函数多少次,该static变量只会被初始化一次。

所以当我第二次调用getInstance函数时,进入getInstance后直接就跳过了TestSingleton的初始化语句,也就是TestSingleton的构造函数,因此最终得到的TestSinglon对象和上次的是同一个。我打断点调试的时候发现确实如此。

从这里我收获了一个小小的道理,单例模式的构造函数不应该传参,如果需要传参的话,这个类就应该被设计为普通类。因为如果需要传参的话,就很根据不同的参数生成不同的类的实例,与单例类“一个类只存在一个对象”的设定不符。


其实道理与下面这个是相似的。

void fun(int i)
{
    static int m(i);
    std::cout << m << "\n";
}

int main()
{
    fun(1);
    fun(2);
}

最终两次的输出结果依然都是1,因为m只被初始化一次。

void fun(int i)
{
    static int m = i;
    std::cout << m << "\n";
}

int main()
{
    fun(1);
    fun(2);
}

最终的输出仍然为两个1,这段和上段代码有点类似于 类的拷贝构造和赋值构造 都是”构造函数”。

void fun(int i)
{
    static int m;
    m = i;
    std::cout << m << "\n";
}

int main()
{
    fun(1);
    fun(2);
}

这样的话输出结果就变成一个1和一个2了。

posted @ 2020-02-24 22:09  机智的小小帅  阅读(210)  评论(0编辑  收藏  举报