单例模式的自动释放

一般来说,程序退出的时候,所有的资源都被回收,但是在使用检测内存泄露的工具比如valgrind时会被检测出来,可以理解为这是一种“假的内存泄漏”。为此,这里分别使用三种方法来避免这个问题。

方案一:嵌套类+静态对象

代码实现:

  1 #include <iostream>                                                                                           
  2 using std::cout;
  3 using std::endl;
  4 
  5 class Signalton
  6 {
  7     class AutoRelease
  8     {
  9     public:
 10         AutoRelease()
 11         {
 12             cout<<"AutoRelease()"<<endl;
 13         }
 14 
 15         ~AutoRelease()
 16         {
 17             if(_pInstance)
 18             {
 19                 delete _pInstance;
 20                 cout<<"~AutoRelease()"<<endl;
 21             }
 22         }
 23     };
 24 public:
 25     static Signalton * getInstance()
 26     {
 27         if(_pInstance==nullptr)
 28         {
 29             _pInstance=new Signalton();
 30         }
 31         return _pInstance;
 32     }
 33 
 34     void destroy()
 35     {
 36         if(_pInstance)
 37             delete _pInstance;
 38     }
 39 
 40     void print()const
 41     {
 42         cout<<"void print()const"<<endl;
 43     }
 44 
 45  
 46 private:
 47     Signalton(){cout<<"Signal()"<<endl;}
 48     ~Signalton(){cout<<"~Signal()"<<endl;}
 49 
 50 private:
 51     static Signalton * _pInstance;
 52     static Signalton  _autoRelease;
 53 };
 54 
 55 //Signalton *Signalton:: _pInstance=nullptr;//饿汉模式
 56 Signalton *Signalton:: _pInstance=Signalton::getInstance();//饱汉模式
 57 
 58 Signalton Signalton:: _autoRelease;
 59 
 60 int main()
 61 {
 62     Signalton * p=Signalton::getInstance();
 63     p->print();
 64 
 65    // p->destroy();
 66 
 67     return 0;
 68 }

方案二:atexit + 静态对象

 #include 
 int atexit(void (*function)(void));

功能:注册终止函数,即main函数结束之后调用。
用法:接受一个无参的函数。exit调用这些注册函数的顺序与它们登记时候的顺序相反。同一个函 数如若登记多次,则也会被调用多次。

代码实现:

  1 #include <stdlib.h>
  2 #include <iostream>
  3 using std::cout;
  4 using std::endl;
  5 
  6 class Signalton
  7 {
  8 public:
  9     static Signalton * getInstance()
 10     {
 11         if(_pInstance==nullptr)
 12         {//因为只能新建对象一次,并所以只回收一次,因此在第一创建对象的时候就注册                                                                   
 13             _pInstance=new Signalton();
 14             atexit(destroy);//在新建对象时,注册结束函数
 15         }
 16         return _pInstance;
 17     }
 18 
 19     static void destroy()
 20     {
 21         if(_pInstance)
 22             delete _pInstance;
 23     }
 24 
 25     void print()const
 26     {
 27         cout<<"void print()const"<<endl;
 28     }
 29 
 30 
 31 private:
 32     Signalton(){cout<<"Signal()"<<endl;}
 33     ~Signalton(){cout<<"~Signal()"<<endl;}
 34 
 35 private:
 36     static Signalton * _pInstance;
 37 };
 38 
 39 //Signalton *Signalton:: _pInstance=nullptr;//饿汉模式
 40 Signalton *Signalton:: _pInstance=Signalton::getInstance();//饱汉模式
 41 
 42 int main()
 43 {
 44     Signalton * p=Signalton::getInstance();
 45     p->print();
 46 
 47    // p->destroy();
 48 
 49     return 0;
 50 }

方案三:atexit + pthread_once

#include 
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void))

功能:本函数使用初值为PTHREAD_ONCE_INIT的once_control变量保证init_routine()函数在多线程执行序列中仅执行一次。使用该函数保证了多线程安全。

  1 #include <pthread.h>                                                                                                          
  2 #include <stdlib.h>
  3 #include <iostream>
  4 using std::cout;
  5 using std::endl;
  6 
  7 class Signalton
  8 {
  9 public:
 10     static Signalton * getInstance()
 11     {
 12         pthread_once(&_once,init);
 13         return _pInstance;
 14     }
 15     //init若不被声明为静态类型,则第一个参数为this指针,便不满足pthread_once传入无参函数的要求
 16     static void init()
 17     {
 18         _pInstance=new Signalton();
 19         atexit(destroy);
 20     }
 21 
 22     static void destroy()
 23     {
 24         if(_pInstance)
 25             delete _pInstance;
 26     }
 27 
 28     void print()const
 29     {
 30         cout<<"void print()const"<<endl;
 31     }
 32 
 33 
 34 private:
 35     Signalton(){cout<<"Signal()"<<endl;}
 36     ~Signalton(){cout<<"~Signal()"<<endl;}
 37 
 38 private:
 39     static Signalton * _pInstance;
 40     static pthread_once_t _once;
 41 };
 42 
 43 //Signalton *Signalton:: _pInstance=nullptr;//饿汉模式
 44 Signalton *Signalton:: _pInstance=nullptr;//饱汉模式
 45 pthread_once_t Signalton::_once=PTHREAD_ONCE_INIT;
 46 
 47 int main()
 48 {
 49     Signalton * p=Signalton::getInstance();
 50     p->print();
 51 
 52    // p->destroy();
 53 
 54     return 0;
 55 }

总结

前两种方法都是可以跨平台的,第三种方法具有平台相关性。

你可能感兴趣的:(C++)