经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
C++实现单例模式的自动释放
来源:jb51  时间:2021/6/15 9:23:22  对本文有异议

单例模式是为了确保某个类只能创建一个对象而设计的。当一个程序的某个类型只允许有一个实例的时候使用。

一般采用动态分配的方式来生成单例对象,这个时候C++程序员就需要考虑内存回收的问题了,所以为了避免在使用单例模式时忘记回收资源而造成内存泄漏的问题,在实现单例模式的时候就使其可以自动被回收。

不带自动释放的单例模式的实现与销毁

我们先来复习一下没有自动回收机制的单例模式的实现和销毁。

单例模式的实现:

  • 将构造函数私有化
  • 在类中定义一个静态的指向本类型的指针变量
  • 定义一个返回值为该类的指针的静态成员函数,在类的外部调用该函数,生成单例对象。

单例模式的销毁:

不能在析构函数中释放那个指向本类型的指针变量
需要用静态的成员函数回收指向本类型的指针变量,然后在类的外部调用该成员函数来销毁该单例对象。

单例模式的自动释放

主要思想是,利用C++栈对象消亡是会自动回收的特点,来自动回收分配在堆上的单例对象,可以通过四种方法:友元类、内部类+静态数据成员、atexit()函数、pthread_once()+atexit()来实现

废话不多说,直接上代码。

1.借助友元类

  1. //利用友元类,实现单例模式的自动释放
  2.  
  3. #include <stdio.h>
  4. #include <iostream>
  5.  
  6. using std::cout;
  7. using std::endl;
  8. using std::cin;
  9.  
  10. class AutoRelease;
  11.  
  12. class Singleton{
  13. //单例模式的类
  14. public:
  15. static Singleton *getInstance();//返回单例指针
  16.  
  17. private:
  18. friend class AutoRelease;
  19. Singleton(); //构造函数和析构函数都得是private
  20. ~Singleton();
  21. static Singleton *_pInstance;
  22. };
  23.  
  24. Singleton *Singleton::getInstance(){
  25. if(_pInstance == nullptr){
  26. _pInstance = new Singleton();
  27. }
  28. return _pInstance;
  29. }
  30.  
  31. Singleton::Singleton()
  32. {
  33. cout << "Singleton()" << endl;
  34. }
  35.  
  36. Singleton::~Singleton(){
  37. cout << "~Singleton()" << endl;
  38. }
  39.  
  40. class AutoRelease{
  41. //用来实现单例的自动释放的类
  42. //应该保存在栈上,程序结束时自动回收单例的资源
  43. public:
  44. AutoRelease(){
  45. cout << "AutoRelease()" << endl;
  46. }
  47. ~AutoRelease(){
  48. cout << "~AutoRelease()" << endl;
  49. if(Singleton::_pInstance == nullptr){
  50. return;
  51. }
  52. delete Singleton::_pInstance;
  53. Singleton::_pInstance = nullptr;
  54. }
  55. };
  56.  
  57. Singleton *Singleton::_pInstance = nullptr; //饱汉模式
  58.  
  59. int main()
  60. {
  61. Singleton *s1 = Singleton::getInstance();
  62. Singleton *s2 = Singleton::getInstance();
  63. AutoRelease at;
  64. printf("s1 = %p\n", s1);
  65. printf("s2 = %p\n", s2);
  66. s1 = nullptr;
  67. s2 = nullptr;
  68. return 0;
  69. }

2.借助内部类和静态数据成员

  1. //利用内部类,实现单例模式的自动释放
  2.  
  3. #include <stdio.h>
  4. #include <iostream>
  5.  
  6. using std::cout;
  7. using std::endl;
  8. using std::cin;
  9.  
  10. class Singleton{
  11. //单例模式的类
  12. public:
  13. static Singleton *getInstance();//返回单例指针
  14.  
  15. private:
  16. friend class AutoRelease;
  17. Singleton(); //构造函数和析构函数都得是private
  18. ~Singleton();
  19. static Singleton *_pInstance;
  20.  
  21. private:
  22. //应该设计为私有类,避免类外的其他成员使用
  23. class AutoRelease{
  24. //用来实现单例的自动释放的内部类
  25. //应该保存在栈上,程序结束时自动回收单例的资源
  26. public:
  27. AutoRelease(){
  28. cout << "AutoRelease()" << endl;
  29. }
  30. ~AutoRelease(){
  31. cout << "~AutoRelease()" << endl;
  32. if(Singleton::_pInstance == nullptr){
  33. return;
  34. }
  35. delete Singleton::_pInstance;
  36. Singleton::_pInstance = nullptr;
  37. }
  38. };
  39.  
  40. private:
  41. static AutoRelease _at; //由于AutoRelease是private,所以对象应该放在静态区
  42. };
  43.  
  44. Singleton *Singleton::getInstance(){
  45. if(_pInstance == nullptr){
  46. _pInstance = new Singleton();
  47. }
  48. return _pInstance;
  49. }
  50.  
  51. Singleton::Singleton()
  52. {
  53. cout << "Singleton()" << endl;
  54. }
  55.  
  56. Singleton::~Singleton(){
  57. cout << "~Singleton()" << endl;
  58. }
  59.  
  60.  
  61. /* Singleton *Singleton::_pInstance = nullptr; //饱汉模式 */
  62. //饱汉模式多线程时不安全,需要使用饿汉模式,在程序跑起来前就生成单例对象
  63. Singleton *Singleton::_pInstance = Singleton::getInstance();//饿汉模式
  64. Singleton::AutoRelease Singleton::_at;
  65.  
  66. int main()
  67. {
  68. Singleton *s1 = Singleton::getInstance();
  69. Singleton *s2 = Singleton::getInstance();
  70. printf("s1 = %p\n", s1);
  71. printf("s2 = %p\n", s2);
  72. s1 = nullptr;
  73. s2 = nullptr;
  74. return 0;
  75. }

3.借助atexit()函数

  1. //利用atexit函数,实现单例模式的自动释放
  2.  
  3. #include <stdio.h>
  4. #include <iostream>
  5.  
  6. using std::cout;
  7. using std::endl;
  8. using std::cin;
  9.  
  10. class Singleton{
  11. //单例模式的类
  12. public:
  13. static Singleton *getInstance();//返回单例指针
  14. static void destroy();
  15.  
  16. private:
  17. friend class AutoRelease;
  18. Singleton(); //构造函数和析构函数都得是private
  19. ~Singleton();
  20. static Singleton *_pInstance;
  21. };
  22.  
  23. Singleton *Singleton::getInstance(){
  24. if(_pInstance == nullptr){
  25. _pInstance = new Singleton();
  26. //注册destroy函数,在进程结束的时候执行,从而自动回收单例
  27. atexit(Singleton::destroy);
  28. }
  29. return _pInstance;
  30. }
  31.  
  32. void Singleton::destroy(){
  33. if(Singleton::_pInstance == nullptr){
  34. return;
  35. }
  36. delete Singleton::_pInstance;
  37. Singleton::_pInstance = nullptr;
  38. }
  39.  
  40. Singleton::Singleton()
  41. {
  42. cout << "Singleton()" << endl;
  43. }
  44.  
  45. Singleton::~Singleton(){
  46. cout << "~Singleton()" << endl;
  47. }
  48.  
  49. //为了保证多线程情况下的安全性,使用饿汉模式
  50. Singleton *Singleton::_pInstance = Singleton::getInstance(); //饿汉模式
  51.  
  52. int main()
  53. {
  54. Singleton *s1 = Singleton::getInstance();
  55. Singleton *s2 = Singleton::getInstance();
  56. printf("s1 = %p\n", s1);
  57. printf("s2 = %p\n", s2);
  58. s1 = nullptr;
  59. s2 = nullptr;
  60. return 0;
  61. }

4.借助pthread_once和atexit函数

  1. //利用pthread_once和atexit函数,实现单例模式的自动释放
  2.  
  3. #include <stdio.h>
  4. #include <iostream>
  5.  
  6. using std::cout;
  7. using std::endl;
  8. using std::cin;
  9.  
  10. class Singleton{
  11. //单例模式的类
  12. public:
  13. static void init();
  14. static Singleton *getInstance();//返回单例指针
  15. static void destroy();
  16.  
  17. private:
  18. friend class AutoRelease;
  19. Singleton(); //构造函数和析构函数都得是private
  20. ~Singleton();
  21. static pthread_once_t _once;
  22. static Singleton *_pInstance;
  23. };
  24.  
  25. void Singleton::init(){
  26. //初始化单例,注册回收函数
  27. if(_pInstance == nullptr){
  28. _pInstance = new Singleton();
  29. atexit(Singleton::destroy);
  30. }
  31. }
  32.  
  33. Singleton *Singleton::getInstance(){
  34. //执行pthread_once,保证在多线程的情况下创建单例对象的安全性
  35. pthread_once(&_once, init);
  36.  
  37. return _pInstance;
  38. }
  39.  
  40. void Singleton::destroy(){
  41. if(Singleton::_pInstance == nullptr){
  42. return;
  43. }
  44. delete Singleton::_pInstance;
  45. Singleton::_pInstance = nullptr;
  46. }
  47.  
  48. Singleton::Singleton()
  49. {
  50. cout << "Singleton()" << endl;
  51. }
  52.  
  53. Singleton::~Singleton(){
  54. cout << "~Singleton()" << endl;
  55. }
  56.  
  57. //由于已经使用了pthread_once来保证安全性,所以使用饱汉模式即可
  58. Singleton *Singleton::_pInstance = nullptr;
  59. /* Singleton *Singleton::_pInstance = Singleton::getInstance(); //饿汉模式 */
  60. pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;
  61.  
  62. int main()
  63. {
  64. Singleton *s1 = Singleton::getInstance();
  65. Singleton *s2 = Singleton::getInstance();
  66. printf("s1 = %p\n", s1);
  67. printf("s2 = %p\n", s2);
  68. s1 = nullptr;
  69. s2 = nullptr;
  70. return 0;
  71. }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号