国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++ 單例模式的各種坑及最佳實踐

這篇具有很好參考價值的文章主要介紹了C++ 單例模式的各種坑及最佳實踐。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

單例模式是設(shè)計模式中最簡單、常見的一種。其主要目的是確保整個進程中,只有一個類的實例,并且提供一個統(tǒng)一的訪問接口。常用于 Logger 類、通信接口類、線程池等。

基本原理

限制用戶直接訪問類的構(gòu)造函數(shù),提供一個統(tǒng)一的 public 接口獲取單例對象。

這里有一個“先有雞還是先有蛋”的問題:

  • 因為用戶無法訪問構(gòu)造函數(shù),所以無法創(chuàng)建對象
  • 因為無法創(chuàng)建對象,所以不能調(diào)用普通的 getInstance() 方法來獲取單例對象

解決這個問題的方法很簡單,將 getInstance() 定義為 static 即可(這也會限制 getInstance() 內(nèi)只能訪問類的靜態(tài)成員)

注意事項

  • 所有的構(gòu)造函數(shù)是 private 的
  • 拷貝構(gòu)造、拷貝賦值運算符需要顯式刪除 =delete,防止編譯器自動合成(即使你顯式定義了析構(gòu)函數(shù)或拷貝構(gòu)造/拷貝賦值運算符,編譯器依然可能合成拷貝賦值運算符/拷貝構(gòu)造!新的 C++ 標準已將該行為標記為 deprecated,但為了兼容舊代碼,目前 C++23 仍然會合成!后面打算單獨用一篇筆記總結(jié)一下編譯器默認合成的函數(shù))

C++ 單例模式的幾種實現(xiàn)方式

版本 1 餓漢式

提前創(chuàng)建單例對象

class Singleton1 {
   public:
    static Singleton1* getInstance() { return &inst; }
    Singleton1(const Singleton1&) = delete;
    Singleton1& operator=(const Singleton1&) = delete;

   private:
    Singleton1() = default;
    static Singleton1 inst;
};

Singleton1 Singleton1::inst;

這個版本在程序啟動時創(chuàng)建單例對象,即使沒有使用也會創(chuàng)建,浪費資源。

版本 2 懶漢式

版本 2 通過將單例對象的實例化會推遲到首次調(diào)用 getInstance(),解決了上面的問題。

class Singleton2 {
   public:
    static Singleton2* getInstance() {
        if (!pSingleton) {
            pSingleton = new Singleton2();
        }
        return pSingleton;
    }
    Singleton2(const Singleton2&) = delete;
    Singleton2& operator=(const Singleton2&) = delete;

   private:
    Singleton2() = default;
    static Singleton2* pSingleton;
};

Singleton2* Singleton2::pSingleton = nullptr;

版本 3 線程安全

在版本 2 中,如果多個線程同時調(diào)用 getInstance() 則有可能創(chuàng)建多個實例。

class Singleton3 {
   public:
    static Singleton3* getInstance() {
        lock_guard<mutex> lck(mtx);
        if (!pSingleton) {
            pSingleton = new Singleton3();
        }
        return pSingleton;
    }
    Singleton3(const Singleton3&) = delete;
    Singleton3& operator=(const Singleton3&) = delete;

   private:
    Singleton3() = default;
    static Singleton3* pSingleton;
    static mutex mtx;
};

Singleton3* Singleton3::pSingleton = nullptr;
mutex Singleton3::mtx;

加鎖可以解決線程安全的問題,但版本 3 的問題在于效率太低。每次調(diào)用 getInstance() 都需要加鎖,而加鎖的開銷又是相當高昂的。

版本 4 DCL (Double-Checked Locking)

版本 4 是版本 3 的改進版本,只有在指針為空的時候才會進行加鎖,然后再次判斷指針是否為空。而一旦首次初始化完成之后,指針不為空,則不再進行加鎖。既保證了線程安全,又不會導(dǎo)致后續(xù)每次調(diào)用都產(chǎn)生鎖的開銷。

class Singleton4 {
   public:
    static Singleton4* getInstance() {
        if (!pSingleton) {
            lock_guard<mutex> lck(mtx);
            if (!pSingleton) {
                pSingleton = new Singleton4();
            }
        }
        return pSingleton;
    }
    Singleton4(const Singleton4&) = delete;
    Singleton4& operator=(const Singleton4&) = delete;

   private:
    Singleton4() = default;
    static Singleton4* pSingleton;
    static mutex mtx;
};

Singleton4* Singleton4::pSingleton = nullptr;
mutex Singleton4::mtx;

DCL 在很長一段時間內(nèi)被認為是 C++ 單例模式的最佳實踐。但也有文章表示 DCL 的正確性取決于內(nèi)存模型,關(guān)于這部分的深入討論可以參考這兩篇文章:

  • https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
  • https://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/

版本 5 Meyers’ Singleton

這個版本利用局部靜態(tài)變量來實現(xiàn)單例模式。最早由 C++ 大佬、Effective C++ 系列的作者 Scott Meyers 提出,因此也被稱為 Meyers’ Singleton

"This approach is founded on C++'s guarantee that local static objects are initialized when the object's definition is first encountered during a call to that function." ... "As a bonus, if you never call a function emulating a non-local static object, you never incur the cost of constructing and destructing the object."
—— Scott Meyers

TLDR:這就是 C++11 之后的單例模式最佳實踐,沒有之一。

  • 最簡潔:不需要額外定義類的靜態(tài)成員
  • 線程安全,不需要額外加鎖
  • 沒有煩人的指針
class Singleton5 {
   public:
    static Singleton5& getInstance() {
        static Singleton5 inst;
        return inst;
    }

    Singleton5(const Singleton5&) = delete;
    Singleton5& operator=(const Singleton5&) = delete;

   private:
    Singleton5() = default;
};

我曾見到過有人畫蛇添足地返回單例指針,就像下面這樣

static Singleton* getInstance() {
    static Singleton inst;
    return &inst;
}

如果沒什么正當?shù)睦碛桑ㄎ乙矊嵲谙氩坏接惺裁蠢碛桑€是老老實實地返回引用吧?,F(xiàn)代 C++ 應(yīng)當避免使用裸指針,關(guān)于這一點,我也有一篇筆記:裸指針七宗罪文章來源地址http://www.zghlxwxcb.cn/news/detail-479160.html

到了這里,關(guān)于C++ 單例模式的各種坑及最佳實踐的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【C++】設(shè)計模式-單例模式

    【C++】設(shè)計模式-單例模式

    目錄 一、單例模式 單例模式的三個要點 針對上述三要點的解決方案 常用的兩類單例模式 ?二、懶漢模式實現(xiàn) 1.基本實現(xiàn) 2.鎖+靜態(tài)成員析構(gòu)單例 3.雙層檢查鎖定優(yōu)化 4.雙層檢查鎖定+智能指針 三、餓漢模式實現(xiàn) 1.基礎(chǔ)實現(xiàn) 2.嵌套內(nèi)部類解決內(nèi)存泄漏 3.智能指針解決內(nèi)存泄漏

    2024年02月16日
    瀏覽(16)
  • C++設(shè)計模式:單例模式(十)

    C++設(shè)計模式:單例模式(十)

    1、單例設(shè)計模式 單例設(shè)計模式,使用的頻率比較高,整個項目中某個特殊的類對象只能創(chuàng)建一個 并且該類只對外暴露一個public方法用來獲得這個對象。 單例設(shè)計模式又分懶漢式和餓漢式,同時對于懶漢式在多線程并發(fā)的情況下存在線程安全問題 餓漢式:類加載的準備階段

    2024年04月14日
    瀏覽(33)
  • 【設(shè)計模式】C++單例模式詳解

    ?個類僅有?個實例,并提供一個訪問它的全局訪問點,該實例被所有程序模塊共享。 那么,我們必須保證: 該類不能被復(fù)制;也不能被公開的創(chuàng)造。 對于 C++ 來說,它的構(gòu)造函數(shù),拷貝構(gòu)造函數(shù)和賦值函數(shù)都不能被公開調(diào)用。 單例模式又分為 懶漢模式 和 餓漢模式 ,它們

    2024年02月05日
    瀏覽(23)
  • C++設(shè)計模式代碼--單例模式

    參考:5. 單例模式(Singleton) (yuque.com) 1、什么是單例模式 保證一個類只有一個實例,并提供一個訪問該實例的全局節(jié)點; 2、什么情況下需要單例模式 某個類的對象在軟件運行之初就創(chuàng)建,并且在軟件的很多地方都需要讀寫這個類的信息;使用單例模式的話,類對象就只要

    2024年02月03日
    瀏覽(31)
  • Java 設(shè)計模式最佳實踐:6~9

    原文:Design Patterns and Best Practices in Java 協(xié)議:CC BY-NC-SA 4.0 譯者:飛龍 本文來自【ApacheCN Java 譯文集】,采用譯后編輯(MTPE)流程來盡可能提升效率。 這一章將描述反應(yīng)式編程范式,以及為什么它能很好地適用于帶有函數(shù)元素的語言。讀者將熟悉反應(yīng)式編程背后的概念。我們

    2023年04月14日
    瀏覽(23)
  • C++的單例模式

    忘記之前有沒有寫過單例模式了。 再記錄一下: 我使用的代碼: 雙鎖單例: 單例模式的不同實現(xiàn)方式各有優(yōu)缺點 雙檢鎖(Double Checked Locking): 優(yōu)點: 線程安全。 在實例已經(jīng)被創(chuàng)建之后,直接返回實例,避免了每次獲取實例時都需要獲取鎖的開銷。 缺點: 代碼相對復(fù)雜

    2024年02月10日
    瀏覽(26)
  • C++單例模式

    1.什么是單例模式 單例模式是指在整個系統(tǒng)生命周期內(nèi),保證一個類只能產(chǎn)生一個實例,確保該類的唯一性。 2.單例模式分類 單例模式可以分為 懶漢式 和 餓漢式 ,兩者之間的區(qū)別在于創(chuàng)建實例的時間不同。 懶漢式 系統(tǒng)運行中,實例并不存在,只有當需要使用該實例時,才

    2024年02月05日
    瀏覽(25)
  • C++之單例模式

    單例模式(Singleton Pattern)是 面向?qū)ο笾凶詈唵蔚脑O(shè)計模式之一。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式。 這種模式涉及到一個單一的類,該類負責(zé)創(chuàng)建自己的對象,同時確保只有單個對象被創(chuàng)建。這個類提供了一種訪問其唯一的對象的方式

    2024年01月23日
    瀏覽(33)
  • 單例模式——C++版本

    在一個項目中,全局范圍內(nèi),某個類的實例有且僅有一個,通過這個唯一實例向其他模塊提供數(shù)據(jù)的全局訪問,這種模式就叫單例模式。 類中多對象的操作函數(shù)有如下幾個: 構(gòu)造函數(shù) : 能夠創(chuàng)建出一個新對象; 拷貝構(gòu)造函數(shù) :能夠根據(jù)一個已經(jīng)存在的對象拷貝出一個新對

    2024年02月09日
    瀏覽(17)
  • C++學(xué)習(xí)—單例模式

    C++學(xué)習(xí)—單例模式

    目錄 ?編輯 一,單例模式介紹 二,單例模式下的兩種模式 ?1,餓漢模式 2,懶漢模式 ? 單例:在全局只有一份實例。 單例模式是編程的經(jīng)典模式之一。 二,單例模式下的兩種模式 ?1,餓漢模式 餓漢模式:在main函數(shù)啟動前就先把實例化的類對象準備好。 1,提前準備好實

    2024年02月19日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包