C++之单例模式
来源:互联网 发布:mac把图标放在桌面 编辑:程序博客网 时间:2024/06/05 07:22
C++之单例模式
单例模式也称为单件模式、单子模式,可能是使用最广泛的设计模式。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。有很多地方需要这样的功能模块,如系统的日志输出,GUI应用必须是单鼠标,MODEM的联接需要一条且只需要一条电话线,操作系统只能有一个窗口管理器,一台PC连一个键盘。
方法一:饿汉模式,即指单例实例在程序运行时被立即执行初始化
class Singleton {public: static Singleton * Instance() { return &m_pInstance; }private: Singleton (); // ctor is hidden Singleton (Singleton const&); // copy ctor is hidden static Singleton m_pInstance;};// in Singleton.cpp we have to addSingleton Singleton ::m_pInstance;
此种方法不足:如果有两个单例模式的类 ASingleton 和 BSingleton, 某天你想在 BSingleton 的构造函数中使用 ASingleton 实例, 这就出问题了. 因为 BSingleton m_pInstance 静态对象可能先 ASingleton 一步调用初始化构造函数, 结果 ASingleton::Instance() 返回的就是一个未初始化的内存区域, 程序还没跑就直接崩掉.
方法二:懒汉模式,即单例实例只在第一次被使用时进行初始化
class Singleton {public: static Singleton* Instance() { if (!m_pInstance) m_pInstance = new Singleton; return m_pInstance; }private: Singleton(); // ctor is hidden Singleton(Singleton const&); // copy ctor is hidden static Singleton* m_pInstance;};// in .cpp we have to addSingleton* Singleton::m_pInstance = NULL;
Instance() 只在第一次被调用时为 m_pInstance 分配内存并初始化. 嗯, 看上去所有的问题都解决了, 初始化顺序有保证, 多态也没问题.
不过细心的你可能已经发现了一个问题, 程序退出时, 析构函数没被执行. 这在某些设计不可靠的系统上会导致资源泄漏, 比如文件句柄, socket 连接, 内存等等. 幸好 Linux / Windows 2000/XP 等常用系统都能在程序退出时自动释放占用的系统资源. 不过这仍然可能是个隐患,有些系统是不会自动释放的.
对于这个问题, 比较土的解决方法是, 给每个 Singleton 类添加一个 destructor() 方法,采用RAII方法:
class CSingleton:{ public: static CSingleton * GetInstance() private: CSingleton(){}; static CSingleton * m_pInstance; class CGarbo // 它的唯一工作就是在析构函数中删除CSingleton的实例 { public: ~CGarbo() { if (CSingleton::m_pInstance) delete CSingleton::m_pInstance; CSingleton::m_pInstance=-=NULL; } }; static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数};
然后在程序退出时确保调用了每个 Singleton 类的 destructor() 方法, 这么做虽然可靠, 但却很是繁琐。
考虑到线程安全、异常安全,方法二可以做以下扩展:
class Lock { private: CCriticalSection m_cs; public: Lock(CCriticalSection cs) : m_cs(cs) { m_cs.Lock(); } ~Lock() { m_cs.Unlock(); } }; //RAII模式class Singleton { private: Singleton(); Singleton(const Singleton &); Singleton& operator = (const Singleton &); class CGarbo { public: ~CGarbo() { if (CSingleton::m_pInstance){ delete CSingleton::m_pInstance; CSingleton::m_pInstance=-=NULL; } }; static CGarbo Garbo; // 定义一个静态成员,在程序结束时,系统会调用它的析构函数 public: static Singleton *Instantialize(); static Singleton *pInstance; static CCriticalSection cs; }; Singleton* Singleton::pInstance = 0;Singleton* Singleton::Instantialize() { if(pInstance == NULL) { //double check Lock lock(cs); //用lock实现线程安全,用资源管理类,实现异常安全 //使用资源管理类,在抛出异常的时候,资源管理类对象会被析构,析构总 是发生的无论是因为异常抛出还是语句块结束。 if(pInstance == NULL) pInstance = new Singleton(); } return pInstance; }
方法三、最优实现写法
class Singleton {public: static Singleton& Instance() { static Singleton theSingleton; return theSingleton; } private: Singleton(); // ctor hidden Singleton(Singleton const&); // copy ctor hidden Singleton& operator=(Singleton const&); // assign op. hidden ~Singleton(); // dtor hidden};
在 Instance() 函数内定义局部静态变量的好处是, theSingleton的构造函数只会在第一次调用 Instance() 时被初始化, 达到了和 “堆栈版” 相同的动态初始化效果, 保证了成员变量和 Singleton 本身的初始化顺序.
它还有一个潜在的安全措施, Instance() 返回的是对局部静态变量的引用, 如果返回的是指针, Instance() 的调用者很可能会误认为他要检查指针的有效性, 并负责销毁. 构造函数和拷贝构造函数也私有化了, 这样类的使用者不能自行实例化.
另外, 多个不同的 Singleton 实例的析构顺序与构造顺序相反.
同样可以用Lock保证线程安全。
此处的单例模式特点如下:
1. 它有一个指唯一实例的静态指针m_pInstance,并且是私有的。
2. 它有一个公有的函数,可以获取这个唯一的实例,并在需要的时候创建该实例。
3. 它的构造函数是私有的,这样就不能从别处创建该类的实例。
参考链接:
http://stackoverflow.com/questions/86582/singleton-how-should-it-be-used
http://blog.csdn.net/taiyang1987912/article/details/43202271
http://www.cnblogs.com/wxxweb/archive/2011/04/15/2017088.html
http://www.programlife.net/cpp-singleton-memory-retrieve.html
http://stackoverflow.com/questions/270947/can-any-one-provide-me-a-sample-of-singleton-in-c/271104#271104
http://stackoverflow.com/questions/1008019/c-singleton-design-pattern/1008289#1008289
- C++--模式之单例模式
- (C#)设计模式 之 单例模式
- 设计模式之单例模式(C++)
- C#--设计模式之单例模式
- Objective-C 设计模式之单例
- 初识Objecive-C 之 单例模式
- Objective-C之单例设计模式
- Object-c之单例模式
- qt (c++) 之 单例模式
- 【C++】单例模式之C++实现
- 设计模式之单例模式(C++)
- C语言和设计模式(之单例模式)
- Objective-C中的设计模式之单例模式
- C#单例模式
- C#-单例模式
- 单例模式(C++)
- 【C++】单例模式
- [C++]单例模式
- Codeforces Round #318 [RussianCodeCup Thanks-Round] (Div. 2)
- SGU106 The equation(数论)
- Android基础 学习之List 和 Adapter
- 关于pow函数。
- jQuery 的选择器
- C++之单例模式
- hdu3054(斐波那契。。。。找规律)
- pazu使用指南
- OC的手动内存管理
- Android UI 优化方向
- 0910Android基础MediaPlayer
- 剑指Offer系列---(17)调整数组顺序使奇数位于偶数前面
- 仅用O(1)的空间,将整数数组按奇偶数分成2部分,数组左边是奇数、右边是偶数
- UITableView 基础知识