单例模式的应用场景:ios
一、windows的任务管理器,没法打开两个任务管理器。windows
二、windows的回收站。安全
三、网站的计数器,通常也是采用单例模式实现,不然难以同步多线程
四、 应用程序的日志应用,通常都何用单例模式实现,这通常是因为共享的日志文件一直处于打开状态,由于只能有一个实例去操做,不然内容很差追加。函数
1、单例模式类CSingleton有如下几个特性:性能
一、它有一个指向惟一实例的静态指针m_pInstance,而且是私有的。网站
二、它有一个公有的函数,能够获取建立的这个惟一的实例,而且在须要的时候建立该实例。spa
三、它的构造函数是私有的,这样就不能从别处建立该类的实例。线程
代码以下:指针
class CSingleton { private: CSingleton() //构造函数是私有的 { } static CSingleton *m_pInstance; public: static CSingleton * GetInstance() { if(m_pInstance == NULL) //判断是否第一次调用 m_pInstance = new CSingleton(); return m_pInstance; } };
2、m_pInstance指向的空间何时释放?该实例的析构函数何时执行?
一、须要知道一点:程序在结束的时候,系统会自动析构全部的全局变量。事实上,系统也会析构全部的类的静态成员变量,就像这些静态成员也是全局变量同样。
二、如上所述,咱们能够利用这个特征,咱们能够在单例类中定义一个这样的静态成员变量,而它的惟一工做就是在析构函数中删除单例类的实例。例以下面代码中的CGarbo类。(Garbo意为垃圾工人)
class CSingleton { private: CSingleton() { } static CSingleton *m_pInstance; class CGarbo //它的惟一工做就是在析构函数中删除CSingleton的实例 { public: ~CGarbo() { if(CSingleton::m_pInstance) delete CSingleton::m_pInstance; } }; static CGarbo Garbo; //定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数 public: static CSingleton * GetInstance() { if(m_pInstance == NULL) //判断是否第一次调用 m_pInstance = new CSingleton(); return m_pInstance; } };
CGaibo类是Csingleton类私有内嵌类,防止改类在别的地方被滥用。
程序结束的时候,系统会调用CSingleton类中的CGarbo类的析构函数,该析构函数会删除单例的惟一的实例。
使用这种方式释放单例对象有如下特征:
完整的代码以下:
#include <iostream> using namespace std; class CSingleton { public: static CSingleton *GetInstance(); private: CSingleton() { cout << "CSingleton ctor" << endl; } ~CSingleton() { cout << "CSingleton dtor" << endl; } static CSingleton *m_pInstance; class Garbo { public: ~Garbo() { if (CSingleton::m_pInstance) { cout << "Garbo dtor" << endl; delete CSingleton::m_pInstance; } } }; static Garbo garbo; }; CSingleton::Garbo CSingleton::garbo; // 必定要初始化,否则程序结束时不会析构garbo CSingleton *CSingleton::m_pInstance = NULL; CSingleton *CSingleton::GetInstance() { if (m_pInstance == NULL) m_pInstance = new CSingleton; return m_pInstance; } int main() { CSingleton *p1 = CSingleton::GetInstance(); CSingleton *p2 = CSingleton::GetInstance(); if (p1 == p2) cout << "p1 == p2" << endl; return 0; }
补:
一、饿汉模式:
即第一次调用该类实例的时候才产生一个新的该类实例,并在之后仅返回此实例。
须要用锁,来保证其线程安全性:缘由:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety.
使用double-check来保证thread safety.可是若是处理大量数据时,该锁才成为严重的性能瓶颈。
二、懒汉模式:
即不管是否调用该类的实例,在程序开始时就会产生一个该类的实例,并在之后仅返回此实例。
由静态初始化实例保证其线程安全性,WHY?由于静态实例初始化在程序开始时进入主函数以前就由主线程以单线程方式完成了初始化,没必要担忧多线程问题。
故在性能需求较高时,应使用这种模式,避免频繁的锁争夺。