中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解C++中的單例

發布時間:2020-11-03 16:48:35 來源:億速云 閱讀:136 作者:Leah 欄目:開發技術

本篇文章為大家展示了詳解C++中的單例,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

namespace tlanyan {
  class Foo {
  private:
    static Foo* _instance;
    Foo() {}
    // other members

  public:
    static Foo* getInstance() {
      if (_instance == NULL) {
        _instance = new Foo();
      }
      return _instance;
    }
    ~Foo() {
      // clean codes
    }
    // other members and codes
  };
  Foo* Foo::_instance = NULL;
}

代碼的本意:靜態成員函數getInstance獲取單例指針,并且在析構函數中做一些收尾工作。

運行代碼后發現析構函數死活不執行,難道一個單例模式都能寫錯?反復確認,沒發現問題所在,于是上萬能的StackOverflow上找原因。正好有伙計有同樣的疑惑,有哥們給出了一個可行的方案。根據其答案修改代碼如下:

namespace tlanyan {
  class Foo {
  private:
    Foo() {}
    // other members

  public:
    static Foo& getInstance() {
      static Foo _instance;
      return _instance;
    }
    ~Foo() {
      // clean codes
    }
    // other members and codes
  };
}

對比前一段代碼,主要改動是移除了靜態指針成員,改用函數內的靜態成員。由于_instance是函數內的靜態成員,在首次調用時被初始化(感謝無參構造函數),之后調用將略過初始化而執行后續代碼;函數返回實例的引用,故而每次調用得到的是同一個對象,達到了單例的目的;程序執行結束后,實例的析構函數被自動調用,析構函數中的代碼正確執行。

問題解決了,但什么原因造成第一段單例代碼的析構函數不執行呢?

這是由于C++持有對象的方式造成的(或者說C++允許程序員手動控制內存引起)。Java/PHP等帶有回收機制的語言,持有對象的方式是通過指針,程序員申請對象后會自動分配內存,系統負責跟蹤和回收無用的對象和存在。C++允許開發人員以變量的方式持有對象,例如:Foo foo [= Foo(args)]。變量初始化后獲得對象的引用,離開作用域后,系統銷毀執行棧,對象自動被析構。C++也可以以指針的形式獲得對象的引用: Foo* foo = new Foo(args)。這種方式分配的對象,需要開發人員手動管理。如果不執行delete,對象和分配的內存將一直存在,直到程序退出后,才由操作系統回收。如下代碼可說明這點:

namespace tlanyan {
  void foo() {
    Foo foo;  // 聲明變量,編譯器會自動初始化變量
    Foo* ptr = new Foo();  // 聲明對象指針,同時為對象開辟內存
    // awesome codes
    return;    // 離開作用域, foo對象將被自動析構;如果之前沒有調用過delete ptr, ptr指向的對象將一直存在;如果delete ptr,析構函數將被執行。也可以將ptr指向的對象賦值給外層作用域的指針,此時有多個指針指向同一個變量
  }
}

從上面的代碼可以看出,對象沒有引用計數的情況下,編譯器和系統不敢隨便回收new出來的對象內存:多個指針指向同一個對象,delete了對象可能會導致其他代碼崩潰;釋放內存后,其他指針再delete會多次delete同一塊內存,引發不可預知風險。

綜上,指針單例析構函數沒有被調用的原因是: 自己new的對象,需要自己delete,別指望別人幫你正確調用析構函數。

問題的解決方案有以下幾種:

  1. 同StackOverflow上回答,改用變量方式持有單例對象。程序運行結束前會銷毀所有變量,變量的析構函數將被正確調用;
  2. 在main函數退出前delete單例。例如增加一個destroy的靜態成員函數,將指針指向的對象銷毀;
  3. 使用auto_ptr/unique_ptr等智能指針。

上述內容就是詳解C++中的單例,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

敦煌市| 兴国县| 易门县| 鲁山县| 双江| 遂宁市| 蕲春县| 沛县| 图片| 双牌县| 马公市| 钟祥市| 博野县| 蚌埠市| 从化市| 塔城市| 安庆市| 古蔺县| 浦东新区| 饶阳县| 抚远县| 定襄县| 闸北区| 广饶县| 汝州市| 德安县| 苏尼特右旗| 台南县| 新龙县| 博爱县| 耿马| 治县。| 宣化县| 芒康县| 武穴市| 平罗县| 临泉县| 罗平县| 无极县| 桂东县| 韩城市|