2019/04/08
3,862
单例模式可能是大家最为熟知的一种设计模式,本身没什么好谈的。但是在 C++ 中,由单例模式可以引出一系列的问题,可能会比较有意思,这里探讨一下。
常见的简单实现
1.使用 static 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
class S1 { public: static S1& GetInstance() { static S1 s; return s; } void fun() {} private: S1(){cout<<"S1 inited"<<endl;} S1(const S1&) = delete; S1& operator=(const S1&) = delete; }; class S2{ public: static S2& GetInstance(){ return s; } void fun(){} private: S2(){cout<<"S2 inited"<<endl;} //... private: static S2 s; }; S2 S2::s; |
其中 S2 是要避免的。因为 1. 类的静态成员变量的初始化时间一般早于 main 函数 2. 如果静态成员的初始化里调用了其它类,可能出现未定义的错误。
2.使用指针判断是否初始化
1 2 3 4 5 6 7 8 9 10 11 12 |
class S3{ public: static S3& GetInstance(){ if(s == 0) s = new S3(); return *s; } private: S3(){} static S3 *s; }; |
这两种方式在单线程程序中使用都是可以的,但如果在多线程中,就会出现问题。
Magic Static
对于 S1 要注意, C++ 局部静态变量的初始化可能不是线程安全的 , 这就是 Magic Static
,是指 返回一个静态局部变量的引用 的用法,在某些情况下,如S1 可能会被编译器这样解析: