2019/04/08
5,504
单例模式可能是大家最为熟知的一种设计模式,本身没什么好谈的。但是在 C++ 中,由单例模式可以引出一系列的问题,可能会比较有意思,这里探讨一下。
常见的简单实现
1.使用 static 实现
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.使用指针判断是否初始化
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 可能会被编译器这样解析: