测试代码以下: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了。