单例模式

  1. 单例类保证全局只有一个唯一实例对象。
  2. 单例类提供获取这个唯一实例的接口。

(1).饿汉模式

#include
#include 
using namespace std;

template 
class EagerSingleton
{
public :
                 static T * GetInstance()
                {
                                assert(_instance);
                                 return _instance;
                }
                 //实例销毁(1)一般情况下,不必在乎,因为全局就这一个变量,全局都要用,
                 //不知道什么时候销毁比较合适,一般他的生命周期就是软件的生命周期,
                 //软件结束,他就结束了(程序结束时会自动释放它占用的内存资源)
                 //(2)当在类中打开了文件句柄,数据库连接等,需要手动释放时,就得显示销毁这个实例
                 static void DelInstance()
                {
                                 if (_instance)
                                {
                                                 delete _instance;
                                                _instance = NULL ;
                                }
                }

                 //RAII  自动回收实例对象
                 class GC
                {
                 public :
                                ~GC()
                                {
                                                DelInstance();
                                }
                };
protected :
                EagerSingleton();
                EagerSingleton( const EagerSingleton & s);
                 EagerSingleton & operator = (const EagerSingleton& s);
protected :
                 static T * _instance;
};

template 
T * EagerSingleton ::_instance = new T ;

(2).懒汉模式

template 
class LazySingleton
{
public :
                 T * GetInstance()
                {
                                 // 使用双重检查,提高效率,避免高并发场景下每次获取实例对象都进行加锁
                                 if (_instance == NULL )
                                {
                                                mtx.lock();
                                                 if (_instance == NULL )
                                                {
                                                                 //下面的tmp = new LazyEagerSingleton();编译器可能会进行优化
                                                                 //上面的代码分为三个部分:1.分配空间 2.调用构造函数 3. 赋值
                                                                 //编译器优化可能导致2,3重排。这样可能导致高并发场景下,
                                                                 //其他线程获取到未调用构造函数初始化的对象。解决:加入内存栅栏

                                                                 //就相当于,当程序中已存在一个未调用构造函数初始化的对象,时间片到了,
                                                                 //其他线程以为对象已创建好就直接用了,对吧
                                                                 T * tmp = new T;
                                                                MemoryBarrier();
                                                                _instance = tmp;
                                                }
                                                mtx.unlock();
                                }
                                 return _instance;
                }
protected :
                //构造函数定义为私有,限制只能在类内创建对象
                LazySingleton();
                LazySingleton( const LazySingleton & s);
                 LazySingleton & operator=(const LazySingleton& s);

protected :
                 //1.静态成员无须创建任何对象实例就可以访问。
                 //2.静态对象在main函数之前初始化,这时只有主线程运行,所以是线程安全的。
                 static T * _instance;
                 static mutex mtx;
};
template 
T * LazySingleton ::_instance = NULL ;

参考文件:http://blog.csdn.net/lovelion/article/details/8229621