C++|static成员与单例模式
如果需要一个全局对象,如对话框、系统日志、显卡等设备的驱动程序对象、一台PC连接一个键盘等。这样的全局对象只能是一个且是全局的,这就是单例模式,如何实现呢?
1 不能在类外部通过构造函数新建对象:构造函数的访问方式设置为private或protected。同时,拷贝构造函数和赋值运算符也是私有的,以禁止拷贝和赋值。
2 能够通过调用一个成员函数来实例化一个对象:成员函数设置为static,这样可以在没有对象存在的情形下通过类名来调用这一成员函数;
3 需要确保上述成员函数在对象已经存在的情形下不再创建新对象:增加一个本类指针的static数据成员作为条件变量。
如果是多线程,还是可能创建多个实例,需要进行Lock操作(如Boost库支持此操作)。
#include using namespace std;class Singleton{public: static Singleton *GetInstance() // 静态成员函数构造一个实例 {// Lock(); // 多线程时(Boost库支持Lock操作) if (m_Instance == NULL) { m_Instance = new Singleton(); // ① }// UnLock();// static Singleton m_Instance; // ② 多线程时 return m_Instance;// return const_cast (m_Instance); // ③ 常量对象只有一次创建的机会 } static void DestoryInstance() { if (m_Instance != NULL ) { delete m_Instance; m_Instance = NULL ; } } // This is just a operation example int GetTest() { return m_Test; }private: Singleton(){ m_Test = 10; } // 构造函数私有 Singleton::Singleton(const Singleton&) {} // 拷贝构造函数私有 Singleton &Singleton::operator=(const Singleton&) {} // 赋值运算符私有 static Singleton* m_Instance; // 静态数据成员用于判断是否存在类实例 int m_Test; // used for test};Singleton *Singleton ::m_Instance = NULL;int main(int argc , char *argv []){ Singleton *singletonObj = Singleton ::GetInstance(); coutGetTest()
一般的编程观念是,new操作需要和delete操作进行匹配;上述的实现中,添加了一个DestoryInstance的static函数,这也是最简单,最普通的处理方法了;但是,很多时候,很容易忘记调用DestoryInstance函数,就像你忘记了调用delete操作一样。由于怕忘记delete操作,所以就有了智能指针;那么,在单例模型中,没有“智能单例”,怎么办?
在实际项目中,特别是客户端开发,其实是不在乎这个实例的销毁的。因为,全局就这么一个变量,全局都要用,它的生命周期伴随着软件的生命周期,软件结束了,它也就自然而然的结束了,因为一个程序关闭之后,它会释放它占用的内存资源的,所以,也就没有所谓的内存泄漏了。但是,有以下情况,是必须需要进行实例销毁的:
如果类中有一些文件锁、文件句柄、数据库连接等,这些随着程序的关闭而不会立即关闭的资源,必须要在程序关闭前,进行手动释放。
定义一个供单例类使用的内部GC类,用来释放资源。由于程序在结束的时候,系统会自动析构所有的全局变量,实际上,系统也会析构所有类的静态成员变量,就像这些静态变量是全局变量一样。我们知道,静态变量和全局变量在内存中,都是存储在静态存储区的,所以在析构时,是同等对待的。
#include using namespace std;class Singleton{public: static Singleton *GetInstance() { return m_Instance; } int GetTest() { return m_Test; }private: Singleton(){ m_Test = 10; } static Singleton *m_Instance; int m_Test; class GC { public : ~GC() { // We can destory all the resouce here, eg:db connector, file handle and so on if (m_Instance != NULL ) { coutGetTest()
ref:
https://www.cnblogs.com/ring1992/p/9592817.html
-End-
- 标签:
- 编辑:刘柳
- 相关文章