• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++之竹

            無論是太陽下,還是風雨中,都要成長!

            常用鏈接

            統計

            最新評論

            Singleton模式——C++應用(三)

            前面對C++的Singleton模式的探討還都是針對通過靜態變量來創建對象。但學習嘛,多走點總不是壞事。

            接下來就來看看通過 new 來創建單件對象的單件類設計。既然是用 new 來創建了,那自然就不能忽略需要用 delete 來釋放。

            好了,先來看看代碼:

              1// Singleton demo_2: Singleton instance is created by new.
              2// [delete instance manually]
              3
              4#include <Windows.h>
              5#include <iostream>
              6
              7class A 
              8{
              9private:
             10    static A* ms_pInstance;
             11
             12public:
             13    static A& GetInstance();
             14    static void Release();
             15
             16private:
             17    A() : m_nStat1(-1), m_nStat2(-1{
             18        m_nStat1 = 0;
             19        std::cout << "Construct A" << std::endl;
             20        m_nStat2 = 0;
             21    }

             22    A(const A&);
             23
             24public:
             25    ~A() {
             26        m_nStat1 = 0;
             27        std::cout << "Destruct A" << std::endl;
             28        m_nStat2 = 0;
             29    }

             30
             31    void Do() {
             32        ++m_nStat1;
             33        ++m_nStat2;
             34        std::cout << "Called Do() by object of A. [" 
             35            << m_nStat1 << "" 
             36            << m_nStat2 << "]" 
             37            << std::endl;
             38    }

             39
             40private:
             41    int m_nStat1;
             42    int m_nStat2;
             43}
            ;
             44
             45class C
             46{
             47
             48public:
             49    static C& GetInstance();
             50    static void Release();
             51
             52private:
             53    C() : m_nStat(-1{
             54        std::cout << "Construct C" << std::endl;
             55        m_nStat = 0;
             56    }

             57    C(const C&);
             58
             59public:
             60    ~C() {
             61        std::cout << "Destruct C" << std::endl;
             62        m_nStat = 0;
             63    }

             64
             65    void Do() {
             66        ++m_nStat;
             67        std::cout << "Called Do() by object of C. [" 
             68            << m_nStat << "]" 
             69            << std::endl;
             70    }

             71
             72private:
             73    int m_nStat;
             74}
            ;
             75
             76class B
             77{
             78public:
             79    B(int nID) : m_nID(nID) {
             80        std::cout << "Construct B: " << m_nID << std::endl;
             81        A::GetInstance().Do();
             82        C::GetInstance().Do();
             83    }

             84    ~B() {
             85        std::cout << "Destruct B: " << m_nID << std::endl;
             86        A::GetInstance().Do();
             87        C::GetInstance().Do();
             88    }

             89
             90private:
             91    int m_nID;
             92}
            ;
             93
             94//CRITICAL_SECTION g_cs; // used for supporting multithreading to singleton.
             95
             96static B gs_B0(0);
             97B g_B1(1);
             98
             99A* A::ms_pInstance = NULL;
            100A& A::GetInstance()
            101{
            102    if (NULL == ms_pInstance)
            103    {
            104        //EnterCriticalSection(&g_cs);
            105        //if (NULL == ms_pInstance)
            106        //{
            107            ms_pInstance = new A;
            108        //}
            109        //LeaveCriticalSection(&g_cs);
            110    }

            111
            112    return *ms_pInstance;
            113}

            114
            115void A::Release()
            116{
            117    std::cout << "A::Release()" << std::endl;
            118    if (ms_pInstance != NULL)
            119    {
            120        delete ms_pInstance;
            121        ms_pInstance = NULL;
            122    }

            123}

            124
            125C& C::GetInstance()
            126{
            127    static C* s_pInstance = new C;
            128
            129    return *s_pInstance;
            130}

            131
            132void C::Release()
            133{
            134    std::cout << "C::Release()" << std::endl;
            135    delete &GetInstance();
            136}

            137
            138static B gs_B2(2);
            139B g_B3(3);
            140
            141int main(int argc, char * argv[])
            142{
            143    //InitializeCriticalSection(&g_cs);
            144
            145    std::cout << "Enter main" << std::endl;
            146    A::GetInstance().Do();
            147    C::GetInstance().Do();
            148
            149    A::Release();
            150    C::Release();
            151
            152    //DeleteCriticalSection(&g_cs);
            153    system("pause");
            154    return 0;
            155}

            156

            [單件類的線程安全性]

            代碼中,類A和C都是單件類,且都是通過 new 來分配和創建單件對象,在對象的釋放上,也統一的使用Release函數封裝了delete操作,并手動調用。但A的單件和C的單件又是不同的,這個不同就在于 A 是通過將 new 出來的對象指針賦給成員變量,而 C 則將 new 出來的對象指針給了局部靜態變量。可別小看了這個區別哦!!就因為這一不同,結果 A 不是線程安全的,而 C 卻是線程安全的。當然,也可以通過使用臨界區、互斥量等來是 A 變為線程安全,可是,該在什么時候去初始化臨界區或創建互斥量對象等呢?以臨界區為例,按常規的在 main 的頭部進行臨界區的初始化,末尾則進行臨界區的刪除;但是很不幸,程序崩潰了!!因為全局變量在構造是調用了單件A,而單件A創建用到了臨界區,可這是臨界區卻還沒有初始化。
            那么將這臨界區的初始化放到A的構造呢?一樣使用先去初始化。
            放到A::GetInstance()內呢?影響效率,且存在重復初始化。

            放到B的構造呢?還是被反復多次初始化了……。而且,有非B類的更先構造并調用了單件A的全局對象呢?!

            ——看來,從線程安全考慮,單件類A的設計應當被否決了。

             [單件類對象的釋放]

             撇開線程安全問題不看,就上面的Demo,我們將會發現另一個嚴重問題——何時才能調用A和C的Release方法,釋放A和C的單件對象呢?如果,是如Demo中那樣,在main函數末尾進行釋放,那么因為類B的幾個全局對象的析構,將發生如下的糟糕結果:

            • 單件對象A又被再次重新分配,但卻未能得到再次重新分配,從而造成內存泄露。事實上,對象的內部數據也已不再是我們所需要的數據了。
            • 單件對象C,則因為是static而不會再次分配,所以在B的全局對象析構中,將會使用已經析構了的單件C。

            但是,如果我們把Release放入B的析構中,則A將被多次的分配和釋放,而C則被多次調用析構。無奈咯,考慮釋放的困難,這里的A和C的單件類設計方式看來也都還是否決的好!~

             

            posted on 2012-03-13 00:55 青碧竹 閱讀(253) 評論(0)  編輯 收藏 引用 所屬分類: 設計模式

            久久99精品久久久久久不卡| 狠狠色丁香婷婷综合久久来| 精品久久久久久成人AV| 波多野结衣AV无码久久一区| 久久久久亚洲精品男人的天堂| 国产女人aaa级久久久级| 国产精品嫩草影院久久| 国产精品免费看久久久香蕉| 国内精品久久久久影院免费| 久久久噜噜噜久久熟女AA片| 午夜人妻久久久久久久久| 久久亚洲精品成人av无码网站| 国产成人精品免费久久久久| 久久精品人人槡人妻人人玩AV | 一本一本久久A久久综合精品 | 久久成人影院精品777| 久久国产精品免费一区二区三区 | 人妻丰满?V无码久久不卡| 久久天天躁夜夜躁狠狠躁2022 | 国产精品久久久久久搜索| 亚洲欧美日韩精品久久| 久久亚洲精品无码播放| 精品久久久久久无码专区| 国产精品99久久久久久董美香| 午夜精品久久久久9999高清| 一级A毛片免费观看久久精品| 久久久精品人妻一区二区三区蜜桃 | 久久精品国产亚洲av麻豆小说| 久久精品九九亚洲精品天堂| 国产成人久久久精品二区三区 | 久久国产精品免费| 久久久久久狠狠丁香| 日韩va亚洲va欧美va久久| 久久99精品国产自在现线小黄鸭 | 人妻无码久久精品| 久久久久这里只有精品 | 午夜精品久久久久久中宇| 亚州日韩精品专区久久久| 久久久久久a亚洲欧洲aⅴ| 久久水蜜桃亚洲av无码精品麻豆 | 久久se精品一区精品二区国产 |