單例模式簡介以及C 版本的實現

2022-04-16 09:51:14 字數 3906 閱讀 3782

本篇博文主要內容參考 c++的單例模式一文,在此,為原作者耐心細緻的分析講解,表示感謝。本文將結合此篇文章,給出自己做實驗後的理解以及**,作為今天學習的小結。

單例模式,它的意圖是保證乙個類僅擁有乙個例項,並在對外提供乙個全域性訪問點,該例項被所有模組共享。這種模式的應用範圍很廣,比如系統日誌輸出,作業系統的視窗管理器,pc連線的鍵盤等等。

單例模式是一種設計模式,它的具體實現和各種語言特性有關,這裡主要介紹在c++上面的實現,測試平台為win7 64位,vs2010開發環境。

根據參考博文中的例子,在此先列舉一下各種實現策略,以下均以csingleton為類名來舉例。

1. 使用乙個全域性物件,比如就叫csingleton g_instance,優點是訪問方便,缺點是不能保證此類物件唯一,除了全域性物件外,還能夠建立csingleton的區域性例項。

2. 使用類的靜態成員變數,此變數為私有的靜態成員指標,如static csingleton1 *m_pinstance;此時,需要考慮讓類自己在合適的時候釋放掉此成員指標所指向的內容。

3. 使用類的靜態成員變數,此變數為私有的靜態成員,如static csingleton1 m_pinstance;

在給出**前,要說明幾個知識點:

1. 類的靜態成員(包括 成員變數和成員函式),屬於類自身,所有例項物件均共享同一副本。

2. 靜態成員初始化操作在進入main函式之前,就已經分配空間並且完成初始化。靜態成員變數必須在類體外初始化,通過類似 csingleton1* csingleton::m_pinstance = null的方式來定義初始化數值。如果不初始化,那麼此成員就不會被分配空間,也就不會在類中存在。

4. 靜態成員在程式退出main函式後,會轉到crt類函式的清理中,完成程式靜態變數、類的析構函式等資源釋放的呼叫,具體細節就無需考慮,只需要知道退出main函式還需要做清理工作就行。

3. 宣告在類內部的類,成為巢狀類,它一般用來宣告只在類內部使用的類。如果一定要在外部使用,需要加域解析符::

好了,基本鋪墊完成,開始碼**,先從簡單開始。

靜態類變數方式,起先可以是類的成員變數,但需要在外部進行初始化,不優雅。其實,在類的靜態成員函式中宣告靜態區域性類變數,是一種更簡潔的方法。

class csingleton  

csingleton(const csingleton &);

csingleton & operator = (const csingleton &);

public:

static csingleton & getinstance()

};

靜態類指標方式:這種方式實現,因為有分配空間,所以需要考慮的東西比較多。參考c++的單例模式一文中的**,下面給出經過親身實踐後,無記憶體洩露的**。重要的地方,都寫上了注釋,便於大家理解。

// singlethon.cpp : 定義控制台應用程式的入口點。
#include
#include
using

namespace std;

//用於開啟crt 記憶體洩露檢測問題
#define _crtdbg_map_alloc
#include
#include
//多執行緒保護鎖類
class lock
;
lock(const lock&){};
lock& operator=(const lock&){};
public:
lock(critical_section cs):m_cs(cs)
void startlock()
void stoplock()
~lock()
};
//自己仿照參考,實現乙個單例模式
class singlethon
;                        //禁止間接宣告 singlethon single2(*(singlethon::getinstance()));
//      或者   singlethon single2 = (*(singlethon::getinstance()));
singlethon& operator=(const singlethon&){};        //禁止賦值操作     singlethon single;single = *(singlethon::getinstance());
static singlethon* m_pinstance;
static cgarbo garbo;        //靜態成員變數,程式結束時,系統自動呼叫它的析構函式
static critical_section cs;
public:
static singlethon* getinstance();
~singlethon()
};
//以下三句話,缺一不可

singlethon::cgarbo singlethon::garbo;
singlethon* singlethon::m_pinstance = null;
singlethon* singlethon::getinstance()
lock.stoplock();
}    //正常退出或者異常丟擲,這裡都會自動呼叫lock的析構函式,因為lock的作用域是區域性的
return m_pinstance;
}
int main()
上述**有幾個地方要詳細解析一下:

1. 在釋放類的時候,如果類中有動態變數成員,一般要先釋放其中的內容,然後在呼叫析構函式釋放類本身的空間。類似的,比如在vectorarray,如果直接array.clear,其中,分配的記憶體空間就會洩露,正確的方法是,先釋放掉分配的內容,然後清空空間。

for (vector::iterator it = v.begin(); it != v.end(); it ++) 

if (null != *it)

v.clear();

2. 上述**定義了乙個鎖類,封裝了臨界區的相關操作,作為資源管理類,內部有臨界區變數,作為多執行緒安全的保證。區域性資源管理類變數使得,當異常發生時,也能呼叫析構函式,釋放臨界區資源

3. 在進行判斷時,判斷了兩次,提高效率。因為該方法呼叫第一次就產生例項,而pinstance == null 大部分情況下都為false,如果只判斷一次,那麼每次獲取例項前都需要加鎖,效率太低。

4. 定義乙個巢狀類,和對應的靜態區域性變數,這樣,當整個單例釋放之前,就可以通過它來找到單例指標,然後delete掉他,這樣就不會有記憶體洩露傳送了。

5. 使用crt類函式的記憶體洩露檢測功能,方便檢視除錯。

ok!讀者可以在各個構造和析構函式中間加上端點,也可以嘗試注釋掉cgarbo的析構函式除錯,看看有沒有記憶體洩露。

好久沒有更新文章,這段時間工作很忙,忙不可怕,可怕的是沒有目的、沒用動機的忙。

c 實現單例模式以及單例的派生類

單例模式 乙個類只用乙個物件,如果使用者建立多個物件需要返回錯誤,建構函式只能被訪問一次,不能給使用者隨便訪問建構函式的介面,即建構函式不能是public型別的。每個使用者在不知道這個類唯一例項的情況下都可以快速訪問這個物件。那麼就必須有乙個函式需要返回該例項,並且該函式可以不適用物件進行呼叫,那麼...

c 版本之單例模式

單例模式 singleton 是指乙個類僅有乙個例項物件,並且該類提供乙個獲得該例項物件的全域性訪問點,它包含三個關鍵元素 元素一 提供private型別的建構函式 元素二 提供private型別的的靜態成員變數,以儲存唯一的例項物件 元素三 提供獲得本類例項的全域性訪問點getinstance函式...

C 實現單例模式

給所需要進行單例的類ctest的建構函式宣告為private或者protected 防止在類外隨意生成ctest的物件 然後宣告乙個靜態成員變數 instance 乙個靜態成員函式getinsance staticctest getinstance staticctest instance 靜態成員...