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

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

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

      C++從靜態(tài)類型到單例模式

      1. 概述

      很多的知識,學(xué)習(xí)的時(shí)候理解其實(shí)并不是很深,甚至覺得是是不太必要的;而到了實(shí)際使用中遇到了,才有了比較深刻的認(rèn)識。

      2. 詳論

      2.1. 靜態(tài)類型

      2.1.1. 靜態(tài)方法成員

      比如說類的靜態(tài)成員函數(shù)。從學(xué)習(xí)中我們可以知道,類的靜態(tài)成員表示這個(gè)類成員直接屬于類本身;無論實(shí)例化這個(gè)類對象多少次,靜態(tài)成員都只是一份相同的副本。那么什么時(shí)候去使用這個(gè)特性呢?一個(gè)很簡單的例子,假設(shè)我們實(shí)現(xiàn)了很多函數(shù):

      void FunA() {}
      
      void FunB() {}
      
      void FunC() {}
      

      這些函數(shù)如果具有相關(guān)性,都是某個(gè)類型的工具函數(shù),那么我們可以將其封裝成一個(gè)工具類,并將其方法成員都定義成靜態(tài)的:

      class Utils {
      public:
        static void FunA() {}
      
        static void FunB() {}
      
        static void FunC() {}
      };
      

      這樣做的好處很多:

      1. 體現(xiàn)了面向?qū)ο蟮乃枷搿2⑶?,這些方法在類中本來就只需要一份就可以了,節(jié)省了程序內(nèi)存。
      2. 避免在全局作用域定義函數(shù)。一般的編程認(rèn)為,定義在全局作用域的變量或者方法是不太好的。
      3. 方便使用:只用記住Utils這個(gè)類的名字,就可以在IDE輸入提示的幫助下快熟輸入想要的函數(shù)。

      2.1.2. 靜態(tài)數(shù)據(jù)成員

      一個(gè)順理成章的問題就是,既然靜態(tài)方法成員這么好用,那么我們使用靜態(tài)數(shù)據(jù)成員也挺好的吧?一般情況下確實(shí)如此,比如我們給這個(gè)工具類定義一個(gè)靜態(tài)數(shù)據(jù)成員pai:

      class Utils {
      public:
        static void FunA() {}
      
        static void FunB() {}
      
        static void FunC() {}
      
        static double pai;
      };
      
      double Utils::pai = 3.1415926;
      

      但是有一個(gè)問題在于,簡單的數(shù)據(jù)成員能夠通過賦值來初始化,如果是一個(gè)比較復(fù)雜的數(shù)據(jù)成員呢?一個(gè)例子就是std::map容器數(shù)據(jù)成員,需要經(jīng)過多次插入操作來初始化。這個(gè)時(shí)候只是通過賦值就很難實(shí)現(xiàn)了。

      不僅如此,使用類的靜態(tài)數(shù)據(jù)成員還會(huì)遇到一個(gè)相互依賴的問題,如參考文獻(xiàn)2中所述。由于靜態(tài)變量的初始化順序是不定的,很可能會(huì)導(dǎo)致靜態(tài)變量A初始化需要靜態(tài)變量B,但是靜態(tài)變量B卻沒有完成初始化,從而導(dǎo)致出錯(cuò)的問題。

      2.2. 單例模式

      2.2.1. 實(shí)現(xiàn)

      C++并沒有靜態(tài)類和靜態(tài)構(gòu)造函數(shù)的概念。在參考文獻(xiàn)1中,論述了一些用C++去實(shí)現(xiàn)靜態(tài)構(gòu)造函數(shù),從而更加合理的去初始化靜態(tài)數(shù)據(jù)成員的辦法。其中一個(gè)實(shí)現(xiàn)是:我們需要的類按照正常的非靜態(tài)成員類去設(shè)計(jì),但是我們可以把這個(gè)類作為另一個(gè)包裝類的靜態(tài)成員變量,這樣就能完美實(shí)現(xiàn)靜態(tài)構(gòu)造函數(shù)。

      正是這個(gè)實(shí)現(xiàn)給了我靈感:我們想要的不是訪問類的靜態(tài)成員變量,而是單例模式。不想像C一樣使用全局函數(shù)或者全局變量,又不想每次都去實(shí)例化一個(gè)對象,那么我們需要的是單例模式。參考文獻(xiàn)3中給出了單例模式的最佳實(shí)踐:

      class Singleton {
       public:
        ~Singleton() { std::cout << "destructor called!" << std::endl; }
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
        static Singleton& get_instance() {
          static Singleton instance;
          return instance;
        }
      
       private:
        Singleton() { std::cout << "constructor called!" << std::endl; }
      };
      
      int main() {
      
        Singleton& instance_1 = Singleton::get_instance();
        Singleton& instance_2 = Singleton::get_instance();
      
        return 0;
      }
      

      這段代碼的說明如下:

      1. 構(gòu)造函數(shù)和析構(gòu)函數(shù)都存在,無論多復(fù)雜的成員,都可以對數(shù)據(jù)成員初始化和釋放。
      2. 構(gòu)造函數(shù)時(shí)私有的,所以無法直接聲明和定義。
      3. 拷貝構(gòu)造函數(shù)和賦值構(gòu)造函數(shù)都被刪除,因此無法進(jìn)行拷貝和賦值。
      4. 只能通過專門的實(shí)例化函數(shù)get_instance()進(jìn)行調(diào)用。

      在實(shí)例化函數(shù)get_instance()內(nèi)部,實(shí)例化了一個(gè)自身的局部的靜態(tài)類。靜態(tài)局部變量始終存放在內(nèi)存的全局?jǐn)?shù)據(jù)區(qū),只在第一次初始化,從第二次開始,它的值不會(huì)變化,是第一次調(diào)用后的結(jié)果值。并且最后,返回的是這個(gè)靜態(tài)局部變量的引用。

      2.2.2. 問題

      無論從哪方面看,上述的單例實(shí)現(xiàn),都符合單例的設(shè)計(jì)模式:全局只提供唯一一個(gè)類的實(shí)例,在任何位置都可以通過接口獲取到那個(gè)唯一實(shí)例,無法拷貝也無法賦值。但是也有幾個(gè)問題值得討論。

      第一個(gè)問題是,在多線程的環(huán)境下,初始化是否會(huì)造成沖突或者生成了兩份實(shí)例?關(guān)于這一點(diǎn)不用擔(dān)心,從C++11標(biāo)準(zhǔn)開始,局部靜態(tài)變量的初始化是線程安全的。

      第二,在參考文獻(xiàn)4中討論了這樣一個(gè)問題:C++單例模式跨DLL是不是就是會(huì)出問題?靜態(tài)變量是單個(gè)編譯單元的靜態(tài)變量,如果動(dòng)態(tài)庫和可執(zhí)行文件都引用了get_instance()的實(shí)現(xiàn),那么動(dòng)態(tài)庫和可執(zhí)行文件會(huì)分別保有一份自己的實(shí)例。解決方法是要么將get_instance()放入到cpp中,要么使用DLL的模塊導(dǎo)入導(dǎo)出接口的規(guī)則,也就是dllexport和dllimport。

      第三,單例模式還有基于模塊的實(shí)現(xiàn),不過我覺得模板的實(shí)現(xiàn)太復(fù)雜,第二個(gè)問題就是使用模板導(dǎo)致的,這里就不討論了。

      3. 參考

      1. C++靜態(tài)構(gòu)造函數(shù)
      2. 解決靜態(tài)全局變量初始化的相互依賴問題
      3. C++ 單例模式總結(jié)與剖析
      4. C++單例模式跨DLL是不是就是會(huì)出問題?
      posted @ 2022-05-25 13:30  charlee44  閱讀(1087)  評論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产亚洲av产精品亚洲| 亚洲欧美成人一区二区三区| 国产精品无码a∨麻豆| 中文字幕无码不卡一区二区三区| 国产午夜精品理论大片| 三人成全免费观看电视剧高清| 麻豆精品一区二区综合av| AV人摸人人人澡人人超碰| 国产精品中文字幕视频| 狠狠色噜噜狠狠狠狠色综合网| 亚洲精品综合一区二区在线 | 99久久伊人精品综合观看| 成人欧美日韩一区二区三区| 扒开双腿猛进入喷水高潮叫声| 色爱无码av综合区| 无码人妻斩一区二区三区| 欧美交a欧美精品喷水| 精品无码国产一区二区三区51安 | 天堂V亚洲国产V第一次| 国产农村激情免费专区| 宅男噜噜噜66网站高清| 新乡县| 东京道一本热中文字幕| 人妻一区二区三区三区| 少妇人妻偷人精品视频| 91久久精品国产性色也| 日韩有码中文在线观看| 国产精品免费视频网站| 国产福利深夜在线播放| 国产亚洲精品成人aa片新蒲金| 色琪琪丁香婷婷综合久久| 成熟女人特级毛片www免费| 国产精品日韩中文字幕| 无码高潮爽到爆的喷水视频app| 国产va免费精品观看| 亚洲不卡一区二区在线看| 国产在线精品福利91香蕉| 国产精品乱一区二区三区| 亚洲成人av在线系列| 在线精品视频一区二区三四| 天天干天天日|