单例模式的自动释放

本文探讨了在程序退出时如何避免单例模式引发的'假内存泄漏',提出了三种方法:嵌套类+静态对象、atexit + 静态对象以及atexit + pthread_once。前两者为跨平台解决方案,后者则涉及多线程安全性,但可能不适用于所有平台。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一般来说,程序退出的时候,所有的资源都被回收,但是在使用检测内存泄露的工具比如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 <stdlib.h>
 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 <pthread>
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 }

总结

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值