C++實現(xiàn)單例模式的自動釋放
單例模式是為了確保某個類只能創(chuàng)建一個對象而設(shè)計的。當一個程序的某個類型只允許有一個實例的時候使用。
一般采用動態(tài)分配的方式來生成單例對象,這個時候C++程序員就需要考慮內(nèi)存回收的問題了,所以為了避免在使用單例模式時忘記回收資源而造成內(nèi)存泄漏的問題,在實現(xiàn)單例模式的時候就使其可以自動被回收。
不帶自動釋放的單例模式的實現(xiàn)與銷毀
我們先來復習一下沒有自動回收機制的單例模式的實現(xiàn)和銷毀。
單例模式的實現(xiàn):
- 將構(gòu)造函數(shù)私有化
- 在類中定義一個靜態(tài)的指向本類型的指針變量
- 定義一個返回值為該類的指針的靜態(tài)成員函數(shù),在類的外部調(diào)用該函數(shù),生成單例對象。
單例模式的銷毀:
不能在析構(gòu)函數(shù)中釋放那個指向本類型的指針變量
需要用靜態(tài)的成員函數(shù)回收指向本類型的指針變量,然后在類的外部調(diào)用該成員函數(shù)來銷毀該單例對象。
單例模式的自動釋放
主要思想是,利用C++棧對象消亡是會自動回收的特點,來自動回收分配在堆上的單例對象,可以通過四種方法:友元類、內(nèi)部類+靜態(tài)數(shù)據(jù)成員、atexit()函數(shù)、pthread_once()+atexit()來實現(xiàn)
廢話不多說,直接上代碼。
1.借助友元類
//利用友元類,實現(xiàn)單例模式的自動釋放 #include <stdio.h> #include <iostream> using std::cout; using std::endl; using std::cin; class AutoRelease; class Singleton{ //單例模式的類 public: static Singleton *getInstance();//返回單例指針 private: friend class AutoRelease; Singleton(); //構(gòu)造函數(shù)和析構(gòu)函數(shù)都得是private ~Singleton(); static Singleton *_pInstance; }; Singleton *Singleton::getInstance(){ if(_pInstance == nullptr){ _pInstance = new Singleton(); } return _pInstance; } Singleton::Singleton() { cout << "Singleton()" << endl; } Singleton::~Singleton(){ cout << "~Singleton()" << endl; } class AutoRelease{ //用來實現(xiàn)單例的自動釋放的類 //應(yīng)該保存在棧上,程序結(jié)束時自動回收單例的資源 public: AutoRelease(){ cout << "AutoRelease()" << endl; } ~AutoRelease(){ cout << "~AutoRelease()" << endl; if(Singleton::_pInstance == nullptr){ return; } delete Singleton::_pInstance; Singleton::_pInstance = nullptr; } }; Singleton *Singleton::_pInstance = nullptr; //飽漢模式 int main() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); AutoRelease at; printf("s1 = %p\n", s1); printf("s2 = %p\n", s2); s1 = nullptr; s2 = nullptr; return 0; }
2.借助內(nèi)部類和靜態(tài)數(shù)據(jù)成員
//利用內(nèi)部類,實現(xiàn)單例模式的自動釋放 #include <stdio.h> #include <iostream> using std::cout; using std::endl; using std::cin; class Singleton{ //單例模式的類 public: static Singleton *getInstance();//返回單例指針 private: friend class AutoRelease; Singleton(); //構(gòu)造函數(shù)和析構(gòu)函數(shù)都得是private ~Singleton(); static Singleton *_pInstance; private: //應(yīng)該設(shè)計為私有類,避免類外的其他成員使用 class AutoRelease{ //用來實現(xiàn)單例的自動釋放的內(nèi)部類 //應(yīng)該保存在棧上,程序結(jié)束時自動回收單例的資源 public: AutoRelease(){ cout << "AutoRelease()" << endl; } ~AutoRelease(){ cout << "~AutoRelease()" << endl; if(Singleton::_pInstance == nullptr){ return; } delete Singleton::_pInstance; Singleton::_pInstance = nullptr; } }; private: static AutoRelease _at; //由于AutoRelease是private,所以對象應(yīng)該放在靜態(tài)區(qū) }; Singleton *Singleton::getInstance(){ if(_pInstance == nullptr){ _pInstance = new Singleton(); } return _pInstance; } Singleton::Singleton() { cout << "Singleton()" << endl; } Singleton::~Singleton(){ cout << "~Singleton()" << endl; } /* Singleton *Singleton::_pInstance = nullptr; //飽漢模式 */ //飽漢模式多線程時不安全,需要使用餓漢模式,在程序跑起來前就生成單例對象 Singleton *Singleton::_pInstance = Singleton::getInstance();//餓漢模式 Singleton::AutoRelease Singleton::_at; int main() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); printf("s1 = %p\n", s1); printf("s2 = %p\n", s2); s1 = nullptr; s2 = nullptr; return 0; }
3.借助atexit()函數(shù)
//利用atexit函數(shù),實現(xiàn)單例模式的自動釋放 #include <stdio.h> #include <iostream> using std::cout; using std::endl; using std::cin; class Singleton{ //單例模式的類 public: static Singleton *getInstance();//返回單例指針 static void destroy(); private: friend class AutoRelease; Singleton(); //構(gòu)造函數(shù)和析構(gòu)函數(shù)都得是private ~Singleton(); static Singleton *_pInstance; }; Singleton *Singleton::getInstance(){ if(_pInstance == nullptr){ _pInstance = new Singleton(); //注冊destroy函數(shù),在進程結(jié)束的時候執(zhí)行,從而自動回收單例 atexit(Singleton::destroy); } return _pInstance; } void Singleton::destroy(){ if(Singleton::_pInstance == nullptr){ return; } delete Singleton::_pInstance; Singleton::_pInstance = nullptr; } Singleton::Singleton() { cout << "Singleton()" << endl; } Singleton::~Singleton(){ cout << "~Singleton()" << endl; } //為了保證多線程情況下的安全性,使用餓漢模式 Singleton *Singleton::_pInstance = Singleton::getInstance(); //餓漢模式 int main() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); printf("s1 = %p\n", s1); printf("s2 = %p\n", s2); s1 = nullptr; s2 = nullptr; return 0; }
4.借助pthread_once和atexit函數(shù)
//利用pthread_once和atexit函數(shù),實現(xiàn)單例模式的自動釋放 #include <stdio.h> #include <iostream> using std::cout; using std::endl; using std::cin; class Singleton{ //單例模式的類 public: static void init(); static Singleton *getInstance();//返回單例指針 static void destroy(); private: friend class AutoRelease; Singleton(); //構(gòu)造函數(shù)和析構(gòu)函數(shù)都得是private ~Singleton(); static pthread_once_t _once; static Singleton *_pInstance; }; void Singleton::init(){ //初始化單例,注冊回收函數(shù) if(_pInstance == nullptr){ _pInstance = new Singleton(); atexit(Singleton::destroy); } } Singleton *Singleton::getInstance(){ //執(zhí)行pthread_once,保證在多線程的情況下創(chuàng)建單例對象的安全性 pthread_once(&_once, init); return _pInstance; } void Singleton::destroy(){ if(Singleton::_pInstance == nullptr){ return; } delete Singleton::_pInstance; Singleton::_pInstance = nullptr; } Singleton::Singleton() { cout << "Singleton()" << endl; } Singleton::~Singleton(){ cout << "~Singleton()" << endl; } //由于已經(jīng)使用了pthread_once來保證安全性,所以使用飽漢模式即可 Singleton *Singleton::_pInstance = nullptr; /* Singleton *Singleton::_pInstance = Singleton::getInstance(); //餓漢模式 */ pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT; int main() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); printf("s1 = %p\n", s1); printf("s2 = %p\n", s2); s1 = nullptr; s2 = nullptr; return 0; }
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++數(shù)據(jù)結(jié)構(gòu)之鏈表詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之鏈表的創(chuàng)建的相關(guān)資料,希望通過本文幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2021-08-08關(guān)于C語言函數(shù)strstr()的分析以及實現(xiàn)
以下是對C語言中strstr()函數(shù)的使用進行了詳細的分析介紹,需要的朋友可以參考下2013-07-07