保證乙個類只建立乙個例項。
提供對該例項的全域性訪問點。
如果系統有類似的實體(有且只有乙個,且需要全域性訪問),那麼就可以將其實現為乙個單例。實際工作中常見的應用舉例
首先看gof在描述單例模式時提出的一種實現,教科書式的例子,對c++有些經驗應該對該實現都有些印象
//標頭檔案中
class singleton
return *instance_;
}private:
singleton();
~singleton();
singleton(const singleton&);
singleton& operator=(const singleton&);
private:
static singleton* instance_;
};//實現檔案中
singleton* singleton::instance_ = 0;
實現中建構函式被宣告為私有方法,這樣從根本上杜絕外部使用建構函式生成新的例項,同時禁用拷貝函式與賦值操作符(宣告為私有但是不提供實現)避免通過拷貝函式或賦值操作生成新例項。
提供靜態方法instance()
作為例項全域性訪問點,該方法中先判斷有沒有現成的例項,如果有直接返回,如果沒有則生成新例項並把例項的指標儲存到私有的靜態屬性中。
注意,這裡instance()
返回的例項的引用而不是指標,如果返回的是指標可能會有被外部呼叫者delete
掉的隱患,所以這裡返回引用會更加保險一些。並且直到instance()
被訪問,才會生成例項,這種特性被稱為延遲初始化(lazy initialization),這在一些初始化時消耗較大的情況有很大優勢。
lazy singleton不是執行緒安全的,比如現在有執行緒a和執行緒b,都通過instance_ == null
的判斷,那麼執行緒a和b都會建立新例項。單例模式保證生成唯一例項的規則被打破了。
這種實現在程式開始(靜態屬性instance初始化)的時就完成了例項的建立。這正好和上述的lazy singleton相反。
//標頭檔案中
class singleton
private:
singleton();
~singleton();
singleton(const singleton&);
singleton& operator=(const singleton&);
private:
static singleton instance;
}//實現檔案中
singleton singleton::instance;
由於在main函式之前初始化,所以沒有執行緒安全的問題,但是潛在問題在於no-local static物件(函式外的static物件)在不同編譯單元(可理解為cpp檔案和其包含的標頭檔案)中的初始化順序是未定義的。如果在初始化完成之前呼叫instance()
方法會返回乙個未定義的例項。
scott meyers在《effective c++》(item 04)中的提出另一種更優雅的單例模式實現,使用local static物件(函式內的static物件)。當第一次訪問instance()
方法時才建立例項。
class singleton
private:
singleton();
~singleton();
singleton(const singleton&);
singleton& operator=(const singleton&);
};
c++0x之後是該實現執行緒安全的,有興趣可以讀相關的標準草案(section 6.7)編譯器支援程度不一定,但是g++4.0及以上是支援的。
lazy singleton的一種執行緒安全改造是在instance()
中每次判斷是否為null前加鎖,但是加鎖是很慢的。
而實際上只有第一次例項建立的時候才需要加鎖。雙檢測鎖模式被提出來,改造之後大致是這樣
static singleton& instance
() }
return *instance_;
}
既然只需要在第一次初始化的時候加鎖,那麼在這之前判斷一下例項有沒有被建立就可以了,所以多在加鎖之前多加一層判斷,需要判斷兩次所有叫double-checked。理論上問題解決了,但是在實踐中有很多坑,如指令重排、多核處理器等問題讓dclp實現起來比較複雜比如需要使用記憶體屏障,詳細的分析可以閱讀這篇**。
在c++11中有全新的記憶體模型和原子庫,可以很方便的用來實現dclp。這裡不展開。有興趣可以閱讀這篇文章《double-checked locking is fixed in c++11》。
在多執行緒程式設計環境下,儘管pthread_once()呼叫會出現在多個執行緒中,init_routine()函式僅執行一次,pthread_once是很適合用來實現執行緒安全單例。
template
class singleton : boost::noncopyable
static
void
init
() private:
static
pthread_once_t ponce_;
static t* value_;
};template
pthread_once_t singleton::ponce_ = pthread_once_init;
template
t* singleton::value_ = null;
這裡的boost::noncopyable的作用是把建構函式, 賦值函式, 析構函式, 複製建構函式宣告為私有或者保護。
單例模式的實現方法很多,要寫乙個完美的實現很難**也會很複雜。但是掌握基礎的實現還是很必要的,然後在實際應用中不斷地去優化和探索。除了執行緒安全,一些場景下還有需要考慮資源釋放,生命週期等相關問題,可以參見《modern c++ design》中對singleton的討論。
本文作者
kuntzuo
Singleton 單例 模式
singleton 模式的宗旨在於確保某個類只有乙個例項,別且為之提供乙個全域性訪問點。為了防止其他工作人員例項化我們的類,可以為該類建立唯一乙個構造器,並將構造器的可見 設定為私有。值得注意的是,如果我們建立了其他的非私有的構造器,或者根本沒有為該類提 供構造器,那麼其他人員還是能例項化我們的類。...
Singleton 單例 模式
今天看了,單例模式。感覺他的本質就是,控制類例項的個數。特例就是,控制static變數的唯一性,保證各個程式共享著同一例項。乙個例子 package singleton description 這是乙個單例模式的使用demo author kyle goal 實現乙個類僅有乙個例項 singleto...
單例(Singleton)模式
單例模式的特點 singleton模式包含的角色只有乙個,那就是singleton。singleton擁有乙個私有建構函式,確保使用者無法通過new取得singleton的例項。除此之外,該模式中包含乙個靜態私有成員變數instance與靜態公有方法instance。instance方法負責檢驗並例...