<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      設計模式學習(一)單例模式補充——單例模式析構

      前言

      《單例模式學習》中提到了,在單例對象是通過new關鍵字動態分配在堆上的情況下,當程序退出時,不會通過C++的RAII機制自動調用其析構函數。本文討論一下這種現象的原因以及解決方法。

      無法調用析構函數的原因

      在DCLP(雙檢查鎖模式)中,CSingleton中的instance是一個靜態指針變量,被分配在全局/靜態存儲區。而instance所指向的CSingleton實例是通過new創建在堆上的,只能手動調用delete來釋放相關資源(對于單例模式這是無法實現的,因為析構函數私有),無法通過RAII釋放相關資源。
      在程序結束時,instance這個指針變量被銷毀了,但它所指向的內存空間中的CSingleton對象并沒有被顯式銷毀,而是由操作系統去回收這一塊內存(不會調用其析構函數)。然而依賴操作系統來清理資源并不是一個優雅的結束方式,可能會造成文件句柄未關閉、網絡連接未斷開等資源泄漏。

      class CSingleton
      {
      public:
          static CSingleton* getInstance();
          static std::mutex mtx;
      private:
          CSingleton(){}
          ~CSingleton(){}
          CSingleton(const CSingleton&)			 = delete;
          CSingleton& operator=(const CSingleton&) = delete;
      
          static CSingleton* instance;
      };
      
      CSingleton* CSingleton::instance;
      
      CSingleton* CSingleton::getInstance()
      {
          if(nullptr == instance)
          {
              mtx.lock();
              if(nullptr == instance)
              {
                  instance = new CSingleton();
              }
              mtx.unlock();
          }
          return instance;
      }
      

      改進方法

      在討論改進方法時,我們還是傾向于利用C++的RAII機制,而不是手動去控制釋放的時機。

      內嵌回收類

      我們的單例類對象生命周期的開始是在第一次調用時,結束是在程序結束時。

      而且我們知道①靜態成員變量的生命周期是從程序啟動到結束②在靜態成員變量被銷毀時會調用其析構函數

      因此我們可以在單例類中定義一個用于釋放單例類資源的內嵌類,將其析構函數定義為顯式刪除單例對象的操作,然后在單例類中添加一個內嵌類類型的靜態成員變量garbo

      這樣的話,在程序結束時garbo就會被銷毀,而RAII機制確保了在銷毀時會調用內嵌類CGarbo的析構函數。

      因為在~CGarbo()中delete了CSingleton::instance,所以~CSingleton()就會被調用,相關資源得以釋放。

      class CSingleton
      {
      public:
          static CSingleton* getInstance();
      private:
          CSingleton(){std::cout<<"創建了一個對象"<< std::endl;}
          ~CSingleton(){std::cout<<"銷毀了一個對象"<< std::endl;}
          CSingleton(const CSingleton&) 			 = delete;
          CSingleton& operator=(const CSingleton&) = delete;
              
          static CSingleton* instance;
          static std::mutex mtx;
              
          class CGarbo    
          {
          public:
              CGarbo(){}
              ~CGarbo()
              {
                  if(nullptr != CSingleton::instance)    //嵌套類可訪問外層類的私有成員
                  {
                      delete CSingleton::instance;
                      instance = nullptr;
                  }
                   std::cout<<"Garbo worked"<< std::endl;
              }
          };
        
          static CGarbo garbo; //定義一個靜態成員,程序結束時,系統會自動調用它的析構函數
          
      };
        
      CSingleton* CSingleton::instance;
      
      std::mutex CSingleton::mtx;
      
      CSingleton* CSingleton::getInstance()
      {
          ...
      }
      
      CSingleton::CGarbo CSingleton::garbo;    //還需要初始化一個垃圾清理的靜態成員變量
      

      運行結果:

      智能指針

      我們還可以利用智能指針引用計數機制,對資源自動管理:

      //編譯不通過
      class CSingleton
      {
      public:
          static std::shared_ptr<CSingleton> getInstance(); 
      private:
          CSingleton(){std::cout<<"創建了一個對象"<<std::endl;}
          ~CSingleton(){std::cout<<"銷毀了一個對象"<<std::endl;}
          CSingleton(const CSingleton&)            = delete;
          CSingleton& operator=(const CSingleton&) = delete;
      
          static std::shared_ptr<CSingleton> instance;
          static std::mutex mutex;
      };
      
      std::shared_ptr<CSingleton> CSingleton::instance;
      
      std::mutex CSingleton::mutex;
      
      std::shared_ptr<CSingleton> CSingleton::getInstance()
      {
          if (nullptr == instance)
          {
              std::lock_guard<std::mutex> lock(mutex);
              if (nullptr == instance)
              {
                  instance = std::shared_ptr<CSingleton>(new CSingleton());
              }
          }
          return instance; 
      }
      

      注意上述代碼無法通過編譯,原因是當std::shared_ptr被銷毀時,它會嘗試使用delete來銷毀管理的對象。但因為CSingleton的析構函數是私有的,所以無法從外部手動銷毀CSingleton實例。

      要解決這個問題,我們需要在CSingleton中自定義一個刪除器,讓std::shared_ptr能夠調用私有析構函數。

      class CSingleton
      {
      public:
          static std::shared_ptr<CSingleton> getInstance(); 
      private:
          CSingleton(){std::cout<<"創建了一個對象"<<std::endl;}
          ~CSingleton(){std::cout<<"銷毀了一個對象"<<std::endl;}
          CSingleton(const CSingleton&)            = delete;
          CSingleton& operator=(const CSingleton&) = delete;
      
          static std::shared_ptr<CSingleton> instance;
          static std::mutex mutex;
      
          static void deleter(CSingleton* p); //自定義刪除器
      };
      
      std::shared_ptr<CSingleton> CSingleton::instance;
      
      std::mutex CSingleton::mutex;
      
      std::shared_ptr<CSingleton> CSingleton::getInstance()
      {
          if (nullptr == instance)
          {
              std::lock_guard<std::mutex> lock(mutex);
              if (nullptr == instance)
              {
                  instance = std::shared_ptr<CSingleton>(new CSingleton(),CSingleton::deleter);
              }
          }
          return instance; 
      }
      
      void CSingleton::deleter(CSingleton* p)
      {
          delete p;
          std::cout<<"deleter worked"<<std::endl;
      }
      

      測試結果:

      局部靜態變量

      局部靜態變量形式的單例模式也可以完成資源的釋放,詳見《單例模式學習》

      static CSingleton& getInstance() 
      {
          static CSingleton instance;
          return instance;
      }
      

      參考文章

      posted @ 2024-03-19 00:40  paw5zx  閱讀(489)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久久久亚洲欧洲日产国码606| 国产精品自拍中文字幕| 日本边添边摸边做边爱喷水| 国产成人99亚洲综合精品| 国产精品先锋资源站先锋影院| 乐清市| 性xxxx搡xxxxx搡欧美| jizzjizz少妇亚洲水多| 亚洲精品熟女国产| 天天综合色一区二区三区| 福利视频一区二区在线| 国产麻花豆剧传媒精品mv在线| 亚洲国产成人va在线观看天堂 | 毛片av中文字幕一区二区| 亚洲一区成人在线视频| 国产老肥熟一区二区三区| 色就色中文字幕在线视频| 国产精品午夜福利精品| 在线看国产精品自拍内射| 亚欧乱色精品免费观看| 国产国语一级毛片| 成人午夜在线观看日韩| 国产一区二区三区乱码| 国产精品呻吟一区二区三区| 狠狠综合久久综合88亚洲| 2021国产精品一卡2卡三卡4卡| 麻豆av一区二区三区| 日韩激情一区二区三区| 免费看成人aa片无码视频吃奶 | 免费午夜无码片在线观看影院| 久久亚洲国产精品五月天| 99久久国产综合精品成人影院| 久久这里只精品国产2| 免费观看欧美猛交视频黑人| 波多野结衣久久一区二区| 成人亚洲欧美一区二区三区| 91中文字幕一区在线| 麻豆aⅴ精品无码一区二区| 激情内射亚洲一区二区三区| 成人午夜在线观看刺激| 隆安县|