1.功能:
只能有一个实例的类,用于类似计数、内存池的情况。
2.实现方法:
[1]构造函数设置为private,因此不能在外部创建实例。
[2]提供一个public方法访问实例。
[3]析构函数,析构函数是为了销毁这个类的成员变量,private和public都可以,但是析构函数里面不能delete这个类的实例(析构函数里面delete实例本身就是有问题的,因为delete会调用析构函数,析构里面又delete,会造成递归)。
[4]实例销毁方法:一种是定义一个垃圾回收类,自动销毁这个实例;一种是在外面手动delete这个实例;还一种是定义为访问函数里面的静态成员,当程序退出的时候自动释放这个实例。
3.代码实现:
[1]函数内部静态成员变量方式,第一次访问的时候创建实例,并且线程安全:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 class singleton 6 { 7 public: 8 static singleton *get_instance(){ 9 static singleton single; 10 return &single; 11 } 12 private: 13 singleton(){ 14 printf("singleton() called.\n"); 15 } 16 17 ~singleton(){ 18 printf("~singleton() called.\n"); 19 } 20 }; 21 22 23 int main(int argc, char *argv[]) 24 { 25 singleton *s = singleton::get_instance(); 26 return 0; 27 }
输出:
[2]使用静态的成员变量方式,第一次访问的时候创建实例,并且添加了垃圾回收类:
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 5 class singleton 6 { 7 public: 8 static singleton *get_instance(){ 9 if(m_instance == NULL){ 10 m_instance = new singleton(); 11 printf("get_instance() called.\n"); 12 } 13 14 return m_instance; 15 } 16 17 ~singleton(){ 18 printf("~singleton() called.\n"); 19 } 20 21 private: 22 singleton(){ 23 printf("singleton() called.\n"); 24 } 25 26 class gc 27 { 28 public: 29 gc(){ 30 printf("gc() called.\n"); 31 } 32 33 ~gc(){ 34 printf("~gc() called.\n"); 35 if(m_instance != NULL){ 36 delete m_instance; 37 m_instance = NULL; 38 } 39 } 40 }; 41 42 static gc m_gc; 43 static singleton *m_instance; 44 }; 45 46 singleton *singleton::m_instance = NULL; 47 singleton::gc singleton::m_gc; 48 49 int main(int argc, char *argv[]) 50 { 51 singleton *s = singleton::get_instance(); 52 return 0; 53 }
输出:
4.说明:
[1]上面的两种方式没有好坏之分,只是不同的实现方式,其他还有各种方式实现单实例,但是都没什么区别。
[2]关于析构函数,因为private类型的析构函数无法在外部使用delete对象,所以准备在外面手动释放这个类的实例和其他内部成员时,应该把析构函数设置为public,如果想让这个类的所有成员必须在类内部释放(类里面的垃圾回收类中释放),则应该把析构函数设置为private。
[3]多线程使用,就是加上锁处理m_instance实例,和常规的多线程没什么区别。