日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

总结C++单例模式

發(fā)布時間:2024/3/13 c/c++ 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 总结C++单例模式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

單例模式介紹

單例模式涉及到一個單一的類,該類負責創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建。這個類提供了一種訪問其唯一的對象的方式,可以直接訪問,不需要實例化該類的對象。

單例模式有三個關(guān)鍵點:

1、單例類只能有一個實例。
  為此,單例類只能提供私有的構(gòu)造函數(shù),即保證不能隨意創(chuàng)建該類的實例。

2、單例類必須自己創(chuàng)建自己的唯一實例。
  因為構(gòu)造函數(shù)是私有的,其他對象不能創(chuàng)建單例類的實例,只能是單例類自己來創(chuàng)建。

3、單例類必須給所有其他對象提供這一實例。
  外界需要獲取并使用這個單例類的實例,但是由于該類的構(gòu)造函數(shù)是私有的,外界無法通過new去獲取它的實例,那么就必須提供一個靜態(tài)的公有方法,該方法創(chuàng)建或者獲取它本身的靜態(tài)私有對象并返回。

單例類主要解決了一個全局使用的類的頻繁的創(chuàng)建與銷毀。

所以單例模式有以下幾個優(yōu)點: 1、在內(nèi)存里只有一個實例,減少了內(nèi)存的開銷,尤其是頻繁的創(chuàng)建和銷毀實例;2、避免對資源的多重占用。

那單例模式有一個不好的地方就是,單例類沒有接口,不能繼承。

單例模式使用場景

單例模式就是一個類只能被實例化一次 ,也就是只能有一個實例化的對象的類。減少每次都new對象的開銷,節(jié)省系統(tǒng)資源,同時也保證了訪問對象的唯一實例。常用于如下場景:
1.頻繁實例化然后銷毀的對象。
2.創(chuàng)建對象太耗時,消耗太多資源,但又經(jīng)常用到。

單例模式分為懶漢式和餓漢式兩種。

懶漢式

懶漢式:故名思義,懶漢很懶只有餓了才會去找吃的。也就是說,只有在需要使用的時候才會去實例化。

線程不安全的懶漢式

代碼:

#include <iostream> #include <thread> #include <mutex>using namespace std;//常規(guī)的懶漢式單例模式,存在線程安全問題 class Singleton2 { public:static Singleton2* getInstance() {if (instance == NULL) {instance = new Singleton2();}return instance;}void test() {cout << "this is Singleton2..." << endl;}private:Singleton2() { cout << "Singleton2構(gòu)造函數(shù)" << endl; }; //構(gòu)造函數(shù)私有化Singleton2(const Singleton2&) {} //拷貝構(gòu)造函數(shù)私有化Singleton2& operator=(const Singleton2&) {} //賦值運算符私有化static Singleton2* instance; //靜態(tài)成員變量//類中嵌套類,用于自動回收資源class GC {public:~GC() {if (instance != NULL) {delete instance;instance = NULL;cout << "GC2自動回收..." << endl;}cout << "GC2..." << endl;}};static GC gc; }; //靜態(tài)成員變量,類內(nèi)定義,類外初始化 Singleton2* Singleton2::instance = NULL; Singleton2::GC Singleton2::gc;int main() {Singleton2::getInstance()->test();return 0; }

上面的代碼是線程不安全的單例模式。因為,如果兩個線程同時獲取單例類的實例,都發(fā)現(xiàn)實例不存在,因此都會進行實例化,就會產(chǎn)生兩個實例都要賦值給instance。

這里的線程安全指的是:一個線程在初始化某個變量的時候,其他線程執(zhí)行到這個變量的初始化的時候,就會掛起。就是說只有一個線程會執(zhí)行該變量的初始化

單例類中嵌套回收的類的作用是:不用再手動調(diào)用析構(gòu)函數(shù)了。程序退出release對象析構(gòu)時,單例的指針也會隨著析構(gòu)。

結(jié)果:

為了解決上述問題,設(shè)計出線程安全的懶漢式單例模式,需要考慮加鎖。當然也可以不加鎖,使用靜態(tài)局部變量。
線程安全的懶漢式有兩種實現(xiàn)方式,一種是使用靜態(tài)局部變量,另一種是加鎖。

使用靜態(tài)局部變量(C++11)

由于C++11中規(guī)定靜態(tài)成員變量就是線程安全的,所以這種寫法不存在線程安全問題。
原理就是函數(shù)的局部靜態(tài)變量生命周期隨著進程結(jié)束而結(jié)束。

#include <iostream> #include <thread> #include <mutex>using namespace std;//使用靜態(tài)局部變量的懶漢式單例模式 //由于C++11中規(guī)定靜態(tài)成員變量就是線程安全的,所以這種寫法不存在線程安全問題 class Singleton1 { public:static Singleton1* getInstance() {static Singleton1 instance;return &instance;}void test() {cout << "this is Singleton1..." << endl;}private:Singleton1() { cout << "Singleton1構(gòu)造函數(shù)" << endl; } //構(gòu)造函數(shù)私有化Singleton1(const Singleton1&){} //拷貝構(gòu)造函數(shù)私有化Singleton1& operator=(const Singleton1&) {} //賦值運算符私有化 };int main() {Singleton1::getInstance()->test(); //ingleton1構(gòu)造函數(shù) this is Singleton1...return 0; }

結(jié)果:

加鎖的懶漢式

#include <iostream> #include <thread> #include <mutex>using namespace std;//加鎖,解決常規(guī)的懶漢式單例模式,存在線程安全的問題 class Singleton3 { public:static Singleton3* getinstance() {//兩個NULL可以提高獲取實例效率if (instance == NULL) {mtx.lock();if (instance == NULL) {instance = new Singleton3();}mtx.unlock();}return instance;}void test() {cout << "this is Singleton3..." << endl;}private:Singleton3() { cout << "Singleton3構(gòu)造函數(shù)" << endl; }Singleton3(const Singleton3&) {}Singleton3& operator=(const Singleton3&) {}static Singleton3* instance;static mutex mtx; //鎖//類中嵌套類,用于自動回收資源class GC {public:~GC() {if (instance != NULL) {delete instance;instance = NULL;cout << "GC3自動回收..." << endl;}cout << "GC3..." << endl;}};static GC gc; }; Singleton3* Singleton3::instance = NULL; mutex Singleton3::mtx; Singleton3::GC Singleton3::gc;int main() {Singleton3::getinstance()->test();return 0; }

結(jié)果:

餓漢式

餓漢式:餓了肯定要饑不擇食。在單例類定義的時候就進行實例化。
餓漢式?jīng)]有線程安全問題。
代碼:

#include <iostream> #include <thread> #include <mutex>using namespace std;//餓漢式單例模式,不需要加鎖,也不存在線程安全問題 class Singleton4 { public:static Singleton4* getInstance() {return instance;}void test() {cout << "this is Singleton4..." << endl;}private:Singleton4() { cout << "Singleton4構(gòu)造函數(shù)" << endl; }Singleton4(const Singleton4&){}Singleton4& operator=(const Singleton4&) {}static Singleton4* instance;//類中嵌套類,用于自動回收class GC {public:~GC() {if (instance != NULL) {delete instance;instance = NULL;cout << "GC4自動回收..." << endl;}cout << "GC4..." << endl;}};static GC gc; }; Singleton4* Singleton4::instance = new Singleton4(); Singleton4::GC Singleton4::gc;int main() {Singleton4::getInstance()->test();return 0; }

結(jié)果:

c++單例模式為什么不在析構(gòu)函數(shù)中釋放靜態(tài)的單例對象

1、單例中的 new 的對象需要delete釋放。

2、delete釋放對象的時候才會調(diào)用對象的析構(gòu)函數(shù)。

3、如果在析構(gòu)函數(shù)里調(diào)用delete,那么程序結(jié)束時,根本進不去析構(gòu)函數(shù),怎么會delete。

4、如果程序結(jié)束能自動析構(gòu),那么就會造成一個析構(gòu)的循壞,所以new對應(yīng)于delete。

經(jīng)過驗證,如果不手動delete對象,符合第3條,因為只有進行了delete的時候才會執(zhí)行析構(gòu)函數(shù),但是delete是在析構(gòu)函數(shù)中執(zhí)行的,不在外部手動delete,則不會執(zhí)行析構(gòu)函數(shù),所以在析構(gòu)函數(shù)中釋放對象也沒有用。

但是,如果手動delete對象,將會出現(xiàn)死循環(huán),也就是出現(xiàn)了第4條的情況。因為手動delete會調(diào)用析構(gòu)函數(shù),而在析構(gòu)函數(shù)中,又使用了delete靜態(tài)的單例對象,進而又會調(diào)用析構(gòu)函數(shù),這樣就會一直循環(huán)下去,直到棧溢出。

綜上所述,不可以在析構(gòu)函數(shù)中釋放靜態(tài)的單例對象。可以在類中嵌套一個回收的類,用于釋放單例的對象。

如果不在析構(gòu)函數(shù)中釋放靜態(tài)的單例對象,而在外部手動使用delete,會釋放單例的對象嗎?

答案:不會
例如如下代碼:

Singleton2* S2 = Singleton2::getInstance();cout << S2 << endl; //016C5888delete S2;S2 = NULL;cout << S2 << endl; //00000000cout << Singleton2::getInstance() << endl;//016C5888

結(jié)果:

從結(jié)果中可以看出,把Singleton2::getInstance()賦值給S2之后,S2就指向了單例對象的那塊內(nèi)存,但是
即使把S2 delete掉之后,單例對象還是存在的。這有點像與智能指針,總之,無法通過外部的delete刪除單例對象,所以只能在單例類內(nèi)部使用嵌套類來刪除單例對象,防止內(nèi)存泄漏。
參考鏈接:
C++ 單例模式 - 泣血 - 博客園 (cnblogs.com)

C++實現(xiàn)單例模式_Elena-N的博客-CSDN博客_單例模式c++實現(xiàn)

【設(shè)計模式】單例模式,嵌套類實現(xiàn)釋放對象內(nèi)存 - 走看看 (zoukankan.com)

C++單例模式為何要實例化一個對象不全部使用static_C 語言_腳本之家 (jb51.net)

C++單例模式 正確的資源回收方式_ice_ly000的博客-CSDN博客

總結(jié)

以上是生活随笔為你收集整理的总结C++单例模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。