• <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 青碧竹 閱讀(258) 評論(0)  編輯 收藏 引用 所屬分類: 設計模式

            久久综合给合久久狠狠狠97色| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 欧美一区二区三区久久综 | 国产精品欧美久久久久无广告 | 久久精品国产WWW456C0M| 午夜精品久久久久久影视777| 无码任你躁久久久久久老妇App| 一级女性全黄久久生活片免费 | 久久久精品久久久久久| 欧美伊人久久大香线蕉综合| 99久久99这里只有免费的精品| 色综合久久精品中文字幕首页| 香蕉久久夜色精品国产尤物| 国产国产成人精品久久| 久久久久久国产精品无码下载 | 欧美777精品久久久久网| 中文字幕亚洲综合久久菠萝蜜 | 波多野结衣AV无码久久一区| 99久久www免费人成精品| 日产精品久久久久久久性色| 久久亚洲中文字幕精品一区| 久久精品一区二区| 亚洲va中文字幕无码久久| 久久久久亚洲AV成人网人人网站| 伊人久久综合成人网| 亚洲欧美日韩久久精品| 美女写真久久影院| 色综合色天天久久婷婷基地| 热re99久久6国产精品免费| 久久国产欧美日韩精品免费| 久久久久这里只有精品 | 蜜桃麻豆www久久国产精品| 久久精品中文字幕久久| 亚洲中文字幕久久精品无码APP| 久久久久婷婷| 欧美日韩中文字幕久久久不卡| 国産精品久久久久久久| 久久久久久久尹人综合网亚洲 | 久久国产欧美日韩精品免费| 欧美亚洲国产精品久久久久| 亚洲一级Av无码毛片久久精品|