设计模式--单例模式(二)

2014-11-23 23:56:38 · 作者: · 浏览: 1
ton
{
private:
static Singleton *m_instance;
Singleton(){}//隐藏构造函数
Singleton(const Singleton &){}//隐藏拷贝构造函数
Singleton& operator=(const Singleton &a){}//隐藏赋值操作符
~Singleton(){}//隐藏析构函数
class DelInstance
{
public:
~DelInstance()
{
if(Singleton::m_instance)
delete Singleton::m_instance;
}
};
static DelInstance delIns; //负责回收new出来的对象;
public:
static Singleton *getInstance()
{
return m_instance;
}
};
Singleton::DelInstance Singleton::delIns;
Singleton * Singleton::m_instance = new Singleton;
这是属于饿汉模式,即一开始就创建一个类的实例,以后都返回其地址,是线程安全的。
第四种实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Singleton
{
private:
static Singleton s;
Singleton(){}//隐藏构造函数
Singleton(const Singleton &){}//隐藏拷贝构造函数
Singleton& operator=(const Singleton &a){}//隐藏赋值操作符
~Singleton(){}//隐藏析构函数
public:
static Singleton *getInstance()
{
return &s;
}
};
Singleton Singleton::s;
饿汉模式,这种实现定义一个私有的静态对象实例,(注意不能在类中定义自身的非静态对象,因为这样会形成无限循环定义,而静态对象因为保证只有一个副本,因此不会循环定义),这也是线程安全的
第五种实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Singleton
{
private:
Singleton(){}//隐藏构造函数
Singleton(const Singleton &){}//隐藏拷贝构造函数
Singleton& operator=(const Singleton &a){}//隐藏赋值操作符
~Singleton(){}//隐藏析构函数
public:
static Singleton *getInstance()
{
lock();//c++11 可以不用加锁
static Singleton s;
unlock();
return &s;
}
};
懒汉模式,这种实现只有当第一次调用getInstance时定义局部静态变量s,以后直接返回。c++11之前需要加锁,因为变量的初始化操作不是原子操作,不加锁就不是线程安全的的;c++11则不用加锁,因为c++11保证:如果指令逻辑进入一个未被初始化的声明变量,所有并发执行应当等待完成该变量完成初始化(见here)。
注意
对于第一、二、三、四种方式,都有可能导致static initialization order fiasco (可参考here)。因为c++中,在全局或名字空间范围内的全局变量,在一个类中被声明为static,或,在一个文件范围被定义为static。这三种变量统称“非局部静态对象”,这三种对象的初始化顺序“C++”未作明确规定。因此如果有个类在构造函数中调用了getInstance:
struct Foo {
Foo() {
Singleton::getInstance();
}
};
Foo foo;
不能保证foo初始化时,m_instance已经初始化