亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

養(yǎng)成良好的C++編程習(xí)慣之內(nèi)存管理的應(yīng)用詳解

 更新時(shí)間:2013年05月08日 10:36:27   作者:  
"養(yǎng)成良好的編程習(xí)慣"其實(shí)是相當(dāng)綜合的一個(gè)命題,可以從多個(gè)角度、維度和層次進(jìn)行論述和評(píng)判。如代碼的風(fēng)格、效率和可讀性;模塊設(shè)計(jì)的靈活性、可擴(kuò)展性和耦合度等等。要試圖把所有方面都闡述清楚必須花很多的精力,而且也不一定能闡述得全面。因此,本系列文章以軟件開(kāi)發(fā)的基礎(chǔ)問(wèn)題為切入點(diǎn),闡述程序設(shè)計(jì)和代碼編寫方面的細(xì)節(jié)問(wèn)題,以點(diǎn)帶面,旨在激發(fā)大家的思考與總結(jié),希望能為大家?guī)?lái)實(shí)際的幫助

開(kāi)篇導(dǎo)讀        

  雖然本系列文章定位為科普讀物,但本座相信它們不但適合新手們學(xué)習(xí)借鑒,同時(shí)也能引發(fā)老鳥(niǎo)們的反思與共鳴。歡迎大家提出寶貴的意見(jiàn)和反饋 ^_^

  在開(kāi)篇講述本章主要內(nèi)容之前,本座首先用小小篇幅論述一下一種良好的工作習(xí)慣 —— 積累、提煉與求精。在工作和學(xué)習(xí)的過(guò)程中,不斷把學(xué)到的知識(shí)通過(guò)有效的方式積累起來(lái),形成自己的知識(shí)庫(kù),隨著知識(shí)量的擴(kuò)大,就會(huì)得到從量變到質(zhì)變的提升。另外還要不斷地對(duì)知識(shí)進(jìn)行提煉,隨著自己知識(shí)面的擴(kuò)大以及水平的提升,你肯定會(huì)發(fā)現(xiàn)原有知識(shí)庫(kù)存在著一些片面、局限、笨拙甚至錯(cuò)誤。這時(shí),就需要你有精益求精精的態(tài)度和毅力對(duì)知識(shí)庫(kù)進(jìn)行優(yōu)化整理。

  也許以上這些各位都曾想過(guò)去實(shí)施,也明白其中的道理,但是自己就是給自己各種堂而皇之的借口不花時(shí)間去做。這樣說(shuō)吧,技術(shù)之路不好走,這個(gè)行業(yè)有兩項(xiàng)基本要求:1、對(duì)軟件開(kāi)發(fā)工作本身有很大興趣;2、耐得住寂寞。兩者缺一不可,否則還是趁年輕早點(diǎn)轉(zhuǎn)行吧,要不轉(zhuǎn)做軟件行業(yè)的銷售、產(chǎn)品或者管理也行,總之就不要做開(kāi)發(fā) ^_^

--------------------------------------------------------------------------------

內(nèi)存管理相關(guān)問(wèn)題

  一提起 C/C++ 的內(nèi)存管理,大部分人腦海里都立刻涌出 new / delete / malloc / free 等幾個(gè)恐怖的單詞吧?的確,C/C++ 的手工內(nèi)存管理是它們區(qū)別于其他語(yǔ)言的一大特點(diǎn),也像一道屏障立在那些想從其它語(yǔ)言轉(zhuǎn)向 C/C++ 的人士身前。由此也引起各大論壇對(duì) “C++ 人氣低落”和“是否應(yīng)該引入垃圾回收機(jī)制”等相關(guān)話題的劇烈爭(zhēng)論。本座一直無(wú)視這些爭(zhēng)論,其實(shí)并非本座不關(guān)心 C++ 的發(fā)展與命運(yùn),相反,本座十分關(guān)心。雖然從現(xiàn)在的眼光看來(lái),無(wú)論是 C++ 身上有多少硬傷,C++ 委員會(huì)的大爺們和 C++ 編譯器廠商的大佬們?nèi)绾纬敦埼?。畢竟最?ài)就是最愛(ài),殘缺美也是美,不解釋。本座之所以不關(guān)心這些爭(zhēng)論,原因是因?yàn)榭赐噶?,一門語(yǔ)言就像一種人生,是有生命周期的,沒(méi)落只是快慢的問(wèn)題,舊事物總會(huì)被新事物取代,這是客觀規(guī)律不可避免。秦始皇最終不也是沒(méi)找到長(zhǎng)生不老的仙丹么?只要曾經(jīng)發(fā)光發(fā)熱過(guò),在還有價(jià)值的時(shí)候能為大眾所用就已經(jīng)無(wú)憾了。本座在此還要申明一種態(tài)度:本座并不排斥任何語(yǔ)言,相反,本座對(duì)新語(yǔ)言的誕生非常感興趣。會(huì)去了解它們的特點(diǎn),看看它們能幫助解決哪方面的問(wèn)題。正如這幾年,由于工作需要,本座用得最多的是 Java 和一些動(dòng)態(tài)語(yǔ)言(它們的確能解決很多問(wèn)題),而 C/C++ 卻沒(méi)再用了。

  嗯,扯遠(yuǎn)了,我們還是回到正題吧。說(shuō)起 C/C++ 的內(nèi)存管理似乎令人望而生畏,滿屏的 new / delete / malloc / free,OutPut 窗口無(wú)盡的 Memory Leak 警告,程序詭異的 0X00000004 指針異常,仿佛回到那一年我們一起哭過(guò)的日子,你 Hold 得住嗎?其實(shí),現(xiàn)實(shí)并沒(méi)有你想的那么糟糕。只要你付出一點(diǎn)點(diǎn),花一點(diǎn)點(diǎn)心思,沒(méi)錯(cuò)!就一點(diǎn)點(diǎn)而已 —— 用 C++ 類封裝內(nèi)存訪問(wèn),就會(huì)解決你大部分的煩惱,讓你受益終身。以 Windows 程序?yàn)槔?,主要有以下幾種內(nèi)存管理方式:

•虛擬內(nèi)存(Virtual Memory)
•默認(rèn)堆和私有堆(Process Heap & Private Heap)
•內(nèi)存映射文件(File Mapping)
•進(jìn)程堆棧(Heap,其實(shí)就是用 malloc() 或 默認(rèn)的 new 操作符在 Process Heap 里一小塊一小塊地割肉 ^_^)
•棧(Stack,內(nèi)存由調(diào)用者或被調(diào)用者自動(dòng)管理)
   今天我們的主題是封裝,至于每種內(nèi)存模型的概念和 API 的使用方式在這里就不講了,Google 一下就知道。其實(shí)用 C++ 封裝上述前 4 種內(nèi)存訪問(wèn)的原理都差不多,就是在構(gòu)造函數(shù)或其他操作函數(shù)中分配內(nèi)存,然后再在析構(gòu)函數(shù)中確保內(nèi)存被正確釋放。虛擬內(nèi)存、默認(rèn)堆和私有堆的操作方式相似,這里就不一一展示了,有興趣的朋友可以參考本座前幾天發(fā)表的那篇無(wú)人問(wèn)津的文章:《C++ 封裝私有堆(Private Heap)》,哎!下面對(duì)內(nèi)存映射文件的封裝也只稍作介紹、我們主要討論的是使用頻率最高的 malloc() 和 new 的封裝。

--------------------------------------------------------------------------------

 內(nèi)存映射文件

  下面的代碼把 File Mapping 句柄以及從 File Mapping 映射出來(lái)的內(nèi)存分別封裝到 CFileMapping 和 CShareMemory 中,可以直接使用 CShareMemory 可以創(chuàng)建一個(gè) File Mapping 以及映射 File Mapping 的內(nèi)存。

復(fù)制代碼 代碼如下:

class CFileMapping
{
public:
    CFileMapping(   
                    LPCTSTR lpszName,
                    DWORD dwMaximumSizeLow,
                    DWORD dwMaximumSizeHigh                            = 0,
                    HANDLE hFile                                    = INVALID_HANDLE_VALUE,
                    DWORD flProtect                                    = PAGE_READWRITE,
                    LPSECURITY_ATTRIBUTES lpFileMappingAttributes    = NULL
                )
    {
        m_hMap    = ::CreateFileMapping    (
                                            hFile,
                                            lpFileMappingAttributes,
                                            flProtect,
                                            dwMaximumSizeHigh,
                                            dwMaximumSizeLow,
                                            lpszName
                                        );
        ASSERT(IsValid());
    }

    ~CFileMapping()
    {
        if(IsValid())
            VERIFY(::CloseHandle(m_hMap));
    }

    LPVOID ViewMap    (
                        DWORD dwNumberOfBytesToMap,
                        DWORD dwFileOffsetLow,
                        DWORD dwFileOffsetHigh    = 0,
                        DWORD dwDesiredAccess    = FILE_MAP_ALL_ACCESS
                    )
    {
        return ::MapViewOfFile    (
                                    m_hMap,
                                    dwDesiredAccess,
                                    dwFileOffsetHigh,
                                    dwFileOffsetLow,
                                    dwNumberOfBytesToMap
                                );
    }

    BOOL UnViewMap(LPCVOID lpBaseAddress)
    {
        return ::UnmapViewOfFile(lpBaseAddress);
    }

    operator HANDLE    ()    {return m_hMap;}
    BOOL IsValid    ()    {return m_hMap != NULL;}

private:
    HANDLE m_hMap;

    DECLARE_PRIVATE_COPY_CONSTRUCTOR(CFileMapping)
};

class CShareMemory
{
public:
    CShareMemory(DWORD dwSize, LPCTSTR lpszName = NULL)
    : m_fm(lpszName, dwSize)
    {
        ASSERT(dwSize > 0);
    }

    ~CShareMemory()
    {
        for(set<ULONG_PTR>::const_iterator it = m_set.begin(); it != m_set.end(); ++it)
        {
            LPVOID pV = (LPVOID)*it;
            ASSERT(pV);

            m_fm.UnViewMap(pV);
        }

        m_set.clear();
    }

    LPVOID Alloc(DWORD dwNumberOfBytesToMap, DWORD dwFileOffsetLow)
    {
        LPVOID pV = m_fm.ViewMap(dwNumberOfBytesToMap, dwFileOffsetLow);

        if(pV) m_set.insert((ULONG_PTR)pV);

        ASSERT(pV);
        return pV;
    }

    BOOL Free(LPCVOID lpBaseAddress)
    {
        ASSERT(lpBaseAddress);

        set<ULONG_PTR>::iterator it = m_set.find((ULONG_PTR)lpBaseAddress);

        if(it != m_set.end())
            m_set.erase(it);

        return m_fm.UnViewMap(lpBaseAddress);
    }

private:

    CFileMapping    m_fm;
    set<ULONG_PTR>    m_set;

    DECLARE_PRIVATE_COPY_CONSTRUCTOR(CShareMemory)
};


 

  細(xì)心的朋友一定會(huì)發(fā)覺(jué)其實(shí)這樣封裝是有缺點(diǎn)的:首先,CShareMemory 只能做內(nèi)存共享,不能映射到真實(shí)文件(hFile 永遠(yuǎn)為 INVALID_HANDLE_VALUE);第二,可以對(duì) CShareMemory 的 Alloc() 和 Free() 方法進(jìn)一步封裝,利用封裝類的析構(gòu)函數(shù)自動(dòng)調(diào)用 Free(),這樣就可以完全消除 “set<ULONG_PTR> m_set” 這個(gè)屬性了;第三,CFileMapping 也可以把文件句柄一起封裝進(jìn)來(lái),這樣,從 CreateFile() 到 CreateFileMapping() 都受控了。這個(gè)不完美的封裝就權(quán)當(dāng)反面教材吧 ^_^

--------------------------------------------------------------------------------

malloc() 系列函數(shù)

  很多人都建議,在 C++ 中盡量用 new 操作符取代 malloc(),因?yàn)?new 類型安全,自動(dòng)調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)等等。關(guān)于這點(diǎn)本座略有異議,在某些情形下 malloc() 其實(shí)比 new 更好使,效率方面我們可以不計(jì)較(幾乎所有編譯器的 new 操作符都用 malloc() 分配內(nèi)存),從事過(guò)偏底層開(kāi)發(fā)的人都清楚,我們避免不了處理 row data(如:socket 的收發(fā)緩沖區(qū)等)數(shù)據(jù),這類數(shù)據(jù)是非常適合使用 malloc() 的,用 new 分配的內(nèi)存還要停頓下來(lái)想想到底是用 delete、delete[]、::delete、::delete[] 中的哪個(gè)釋放,malloc() 分配的內(nèi)存想都不用想,free() 包打天下,何況人家有 realloc() 可以方便地重新調(diào)整內(nèi)存,你有沒(méi)有 “renew” 呢?總之一句話,malloc() 的確是有存在的必要,就看接下來(lái)我們?nèi)绾畏庋b它了,請(qǐng)看代碼:

復(fù)制代碼 代碼如下:

// T                 : 數(shù)據(jù)類型(內(nèi)置類型或結(jié)構(gòu)體)
// MAX_CACHE_SIZE    : 預(yù)申請(qǐng)內(nèi)存的最大數(shù)目,以 sizeof(T) 為單位,如果該值設(shè)置合理,對(duì)于
//                     需要?jiǎng)討B(tài)遞增緩沖區(qū)的 buffer 來(lái)說(shuō)能大大提高效率
template<class T, size_t MAX_CACHE_SIZE = 0>
class CBufferPtrT
{
public:
    explicit CBufferPtrT(size_t size = 0, bool zero = false)    {Reset(); Malloc(size, zero);}
    explicit CBufferPtrT(const T* pch, size_t size)    {Reset(); Copy(pch, size);}
    // 拷貝構(gòu)造函數(shù)要分兩種情形
    CBufferPtrT(const CBufferPtrT& other)    {Reset(); Copy(other);}
    template<size_t S> CBufferPtrT(const CBufferPtrT<T, S>& other)    {Reset(); Copy(other);}

    ~CBufferPtrT() {Free();}

    T* Malloc(size_t size = 1, bool zero = false)
    {
        Free();
        return Alloc(size, zero, false);
    }

    T* Realloc(size_t size, bool zero = false)
    {
        return Alloc(size, zero, true);
    }

    void Free()
    {
        if(m_pch)
        {
            free(m_pch);
            Reset();
        }
    }

    template<size_t S> CBufferPtrT& Copy(const CBufferPtrT<T, S>& other)
    {
        if((void*)&other != (void*)this)
            Copy(other.Ptr(), other.Size());

        return *this;
    }

    CBufferPtrT& Copy(const T* pch, size_t size)
    {
        Malloc(size);

        if(m_pch)
            memcpy(m_pch, pch, size * sizeof(T));

        return *this;
    }

    // 動(dòng)態(tài)擴(kuò)大 buffer
    template<size_t S> CBufferPtrT& Cat(const CBufferPtrT<T, S>& other)
    {
        if((void*)&other != (void*)this)
            Cat(other.Ptr(), other.Size());

        return *this;
    }

    // 動(dòng)態(tài)擴(kuò)大 buffer
    CBufferPtrT& Cat(const T* pch, size_t size = 1)
    {
        size_t pre_size = m_size;
        Realloc(m_size + size);

        if(m_pch)
            memcpy(m_pch + pre_size, pch, size * sizeof(T));

        return *this;
    }

    template<size_t S> bool Equal(const CBufferPtrT<T, S>& other) const
    {
        if((void*)&other == (void*)this)
            return true;
        else if(m_size != other.Size())
            return false;
        else if(m_size == 0)
            return true;
        else
            return (memcmp(m_pch, other.Ptr(), m_size * sizeof(T)) == 0);
    }

    bool Equal(T* pch) const
    {
        if(m_pch == pch)
            return true;
        else if(!m_pch || !pch)
            return false;
        else
            return (memcmp(m_pch, pch, m_size * sizeof(T)) == 0);
    }

    T*    Ptr()    {return m_pch;}
    const T*    Ptr()    const    {return m_pch;}
    T&    Get(int i)    {return *(m_pch + i);}
    const T&    Get(int i)    const    {return *(m_pch + i);}
    size_t    Size()    const    {return m_size;}
    bool    IsValid()    const    {return m_pch != 0;}
    // 啊哈,竟然是類型安全的
    operator    T*    ()    {return Ptr();}
    operator const    T*    ()    const    {return Ptr();}
    // 哇塞,竟然還支持索引訪問(wèn)
    T& operator    []    (int i)    {return Get(i);}
    const T& operator    []    (int i)    const    {return Get(i);}
    bool operator    ==    (T* pv)    const    {return Equal(pv);}
    template<size_t S> bool operator    ==    (const CBufferPtrT<T, S>& other)    {return Equal(other);}
    // 賦值操作符要分兩種情形
    CBufferPtrT& operator    =    (const CBufferPtrT& other)    {return Copy(other);}
    template<size_t S> CBufferPtrT& operator    =    (const CBufferPtrT<T, S>& other)    {return Copy(other);}

private:
    void Reset()    {m_pch = 0; m_size = 0; m_capacity = 0;}
    size_t GetAllocSize(size_t size)    {return max(size, min(size * 2, m_size + MAX_CACHE_SIZE));}

    T* Alloc(size_t size, bool zero = false, bool is_realloc = false)
    {
        if(size >= 0 && size != m_size)
        {
            size_t rsize = GetAllocSize(size);
            if(size > m_capacity || rsize < m_size)
            {
                m_pch = is_realloc                            ?
                    (T*)realloc(m_pch, rsize * sizeof(T))    :
                   (T*)malloc(rsize * sizeof(T))            ;

                if(m_pch || rsize == 0)
                {
                    m_size        = size;
                    m_capacity    = rsize;
                }
                else
                    Reset();
            }
            else
                m_size = size;
        }

        if(zero && m_pch)
            memset(m_pch, 0, m_size * sizeof(T));

        return m_pch;
    }

private:
    T*        m_pch;
    size_t    m_size;
    size_t    m_capacity;
};

// 常用 buffer 類型的 typedef
typedef CBufferPtrT<char>            CCharBufferPtr;
typedef CBufferPtrT<wchar_t>        CWCharBufferPtr;
typedef CBufferPtrT<unsigned char>    CByteBufferPtr;
typedef CByteBufferPtr                CBufferPtr;

#ifdef _UNICODE
    typedef CWCharBufferPtr            CTCharBufferPtr;
#else
    typedef CCharBufferPtr            CTCharBufferPtr;
#endif

  嗯。這里要解釋一下為何需要兩個(gè)拷貝構(gòu)造函數(shù)和賦值操作符重載,首先,編譯器為不同的模板參數(shù)生成不同的類,也就是說(shuō):CBufferPtrT<int, 1> 和 CBufferPtrT<int, 2> 被看作是不同的類,另外,C++ 編譯器為每個(gè)類提供了提供了拷貝構(gòu)造函數(shù)和賦值操作符重載的默認(rèn)實(shí)現(xiàn)(淺拷貝)。因此,上述的第一組拷貝構(gòu)造函數(shù)和賦值操作符重載是改寫編譯器的默認(rèn)實(shí)現(xiàn),第二組拷貝構(gòu)造函數(shù)和賦值操作符重載是處理其它類到本類的轉(zhuǎn)換。

  本座對(duì)這個(gè)封裝灰常滿意(唯一美中不足的就是 cnblogs 的編輯器太坑爹了,把代碼弄亂 ^_^),它并非只是一個(gè)普通的 malloc() 封裝,完全能可以把它看作是一種“支持索引訪問(wèn)的類型安全的動(dòng)態(tài)緩沖區(qū)”。如果把它放在一個(gè) socket 通信類中作為成員屬性,充當(dāng)跨越多個(gè)線程和多個(gè)方法訪問(wèn)的接收緩沖區(qū)和發(fā)送緩沖區(qū)的角色就最適合不過(guò)了(當(dāng)然要自己做同步了)。大家可以調(diào)試一下下面的測(cè)試?yán)?,了解一下它的用法?BR>

復(fù)制代碼 代碼如下:

測(cè)試用例
 int _tmain(int argc, _TCHAR* argv[])
 {
     CBufferPtr buffer;

     unsigned char c1    = 'X';
     unsigned char pc1[] = "123";
     unsigned char pc2[] = "abc";
     buffer.Cat(&c1);
     buffer.Cat(pc1, 3);
     buffer.Cat(pc2, 3);

     CBufferPtrT<unsigned char, 10> buffer2 = buffer;
     buffer2.Cat(buffer);
     buffer2.Realloc(0);

     unsigned char* pc = buffer;
     const unsigned char& c = buffer[5];
     buffer[5] = 'O';

     short i1    = 0x7FFF;
     short pi0[] = {9,9,9};
     short pi1[] = {1,2,3};
     short pi2[] = {4,5,6};
     short pi3[] = {8,8,8};

     CBufferPtrT<short, 10> bufferS(pi0, 3);

     bufferS.Cat(&i1);
     bufferS.Cat(pi1, 3);
     bufferS.Cat(pi2, 3);
     bufferS.Cat(pi3, 3);

     CBufferPtrT<short, 5> bufferS2;
     bufferS2.Malloc(4);

     bufferS2 = bufferS;
     bufferS2.Realloc(30);

     CBufferPtrT<int> bufferI(5, true);

     for(size_t i = 0; i < bufferI.Size(); i++)
         bufferI[i] = i *10;

     bufferI.Malloc();
     bufferI[0] = 123;

     // 下面這行編譯不通過(guò),正好說(shuō)明這個(gè)類是類型安全的
 // bufferI = bufferS;

     return 0;
 }


--------------------------------------------------------------------------------

new & delete

  一說(shuō)到 new 的封裝大家立馬想到的就是智能指針吧!沒(méi)錯(cuò),就是智能指針。但 STL 提供的 auto_ptr 缺陷很多,首先使用起來(lái)不方便,竟然連這種寫法都不支持:“std::auto_ptr<int> pi = new int;”,天理何在?。「珊薜氖遣恢С?jǐn)?shù)組指針(需要 delete[]),另外如果某些類重載了 new 操作符的話使用它也有很多問(wèn)題的,還有其它的很多缺點(diǎn)(我忘記了 ^_^)。不過(guò),C++0x 似乎對(duì)智能指針作了重大改進(jìn),已經(jīng)有支持引用計(jì)數(shù)的智能指針了,但不知是否解決數(shù)組指針和區(qū)分 delete 與 ::delete 的問(wèn)題(本座沒(méi)實(shí)測(cè),要是您知道麻煩告訴一聲 ^_^)。無(wú)論如何,下面代碼列出的智能指針支持區(qū)分 delete / delete[] / ::delete / ::delete[]。算是 auto_ptr 的改良(也沒(méi)有使用引用計(jì)數(shù)),文章篇幅太長(zhǎng)了,測(cè)試用例就不發(fā)了,各位看官自行嘗試吧:

復(fù)制代碼 代碼如下:

/************************************************************************/
/*                       smart_ptr 單實(shí)體或數(shù)組智能指針                    */
/************************************************************************/

template<class _Ty>
struct simple_deleter
{
    static void delete_ptr(_Ty* pv) {delete pv;}
};

template<class _Ty>
struct global_simple_deleter
{
    static void delete_ptr(_Ty* pv) {::delete pv;}
};

template<class _Ty>
struct array_deleter
{
    static void delete_ptr(_Ty* pv) {delete[] pv;}
};

template<class _Ty>
struct global_array_deleter
{
    static void delete_ptr(_Ty* pv) {::delete[] pv;}
};

template<class _Ty, class _Deleter>
class smart_ptr
{
public:
    smart_ptr(_Ty* _Ptr = 0)                    : _Myptr(_Ptr)                {}
    smart_ptr(smart_ptr<_Ty, _Deleter>& _Right)    : _Myptr(_Right.release())    {}

    ~smart_ptr()
    {
        reset();
    }

    smart_ptr<_Ty, _Deleter>& reset(_Ty* _Ptr = 0)
    {
        if (_Ptr != _Myptr)
        {
            if(_Myptr)
                _Deleter::delete_ptr(_Myptr);

            _Myptr = _Ptr;
        }

        return *this;
    }

    smart_ptr<_Ty, _Deleter>& reset(smart_ptr<_Ty, _Deleter>& _Right)
    {
        if (this != &_Right)
            reset(_Right.release());

        return *this;
    }

    _Ty* release()
    {
        _Ty* _Ptr    = _Myptr;
        _Myptr        = 0;

        return _Ptr;
    }

    smart_ptr<_Ty, _Deleter>& operator = (_Ty* _Ptr)                        {return reset(_Ptr);}
    smart_ptr<_Ty, _Deleter>& operator = (smart_ptr<_Ty, _Deleter>& _Right)    {return reset(_Right);}

    bool is_valid        ()    const    {return _Myptr != 0;}
    _Ty& operator *        ()    const    {return *_Myptr;}
    _Ty* get            ()    const    {return _Myptr;}
    _Ty* operator ->    ()    const    {return _Myptr;}
    operator _Ty*        ()    const    {return _Myptr;}

private:
    template<class _Other> smart_ptr<_Ty, _Deleter>                    (const smart_ptr<_Ty, _Other>&);
    template<class _Other> smart_ptr<_Ty, _Deleter>&    reset        (const smart_ptr<_Ty, _Other>&);
    template<class _Other> smart_ptr<_Ty, _Deleter>&    operator =    (const smart_ptr<_Ty, _Other>&);

    template<class _Other> smart_ptr<_Ty, _Deleter>                    (const smart_ptr<_Other, _Deleter>&);
    template<class _Other> smart_ptr<_Ty, _Deleter>&    reset        (const smart_ptr<_Other, _Deleter>&);
    template<class _Other> smart_ptr<_Ty, _Deleter>&    operator =    (const smart_ptr<_Other, _Deleter>&);

protected:
    _Ty* _Myptr;
};


/************************************************************************/
/*                    smart_simple_ptr 單實(shí)體智能指針                      */
/************************************************************************/

template<class _Ty>
class smart_simple_ptr : public smart_ptr<_Ty, simple_deleter<_Ty>>
{
public:
    smart_simple_ptr(_Ty* _Ptr = 0)                                    : smart_ptr(_Ptr)    {}
    smart_simple_ptr(smart_simple_ptr<_Ty>& _Right)                    : smart_ptr(_Right)    {}
    smart_simple_ptr(smart_ptr<_Ty, simple_deleter<_Ty>>& _Right)    : smart_ptr(_Right)    {}

    smart_simple_ptr<_Ty>& operator = (smart_ptr<_Ty, simple_deleter<_Ty>>& _Right)
    {return (smart_simple_ptr<_Ty>&)__super::operator = (_Right);}

    smart_simple_ptr<_Ty>& operator = (smart_simple_ptr<_Ty>& _Right)
    {return (smart_simple_ptr<_Ty>&)__super::operator = (_Right);}

    smart_simple_ptr<_Ty>& operator = (_Ty* _Ptr)
    {return (smart_simple_ptr<_Ty>&)__super::operator = (_Ptr);}

private:
    template<class _Other> smart_simple_ptr<_Ty>                (const smart_ptr<_Ty, _Other>&);
    template<class _Other> smart_simple_ptr<_Ty>&    operator =    (const smart_ptr<_Ty, _Other>&);

    template<class _Other> smart_simple_ptr<_Ty>                (const smart_simple_ptr<_Other>&);
    template<class _Other> smart_simple_ptr<_Ty>&    operator =    (const smart_simple_ptr<_Other>&);
};

/************************************************************************/
/*           smart_gd_simple_ptr 單實(shí)體智能指針 (使用全局 delete)          */
/************************************************************************/

template<class _Ty>
class smart_gd_simple_ptr : public smart_ptr<_Ty, global_simple_deleter<_Ty>>
{
public:
    smart_gd_simple_ptr(_Ty* _Ptr = 0)                                        : smart_ptr(_Ptr)    {}
    smart_gd_simple_ptr(smart_gd_simple_ptr<_Ty>& _Right)                    : smart_ptr(_Right)    {}
    smart_gd_simple_ptr(smart_ptr<_Ty, global_simple_deleter<_Ty>>& _Right)    : smart_ptr(_Right)    {}

    smart_gd_simple_ptr<_Ty>& operator = (smart_ptr<_Ty, global_simple_deleter<_Ty>>& _Right)
    {return (smart_gd_simple_ptr<_Ty>&)__super::operator = (_Right);}

    smart_gd_simple_ptr<_Ty>& operator = (smart_gd_simple_ptr<_Ty>& _Right)
    {return (smart_gd_simple_ptr<_Ty>&)__super::operator = (_Right);}

    smart_gd_simple_ptr<_Ty>& operator = (_Ty* _Ptr)
    {return (smart_gd_simple_ptr<_Ty>&)__super::operator = (_Ptr);}

private:
    template<class _Other> smart_gd_simple_ptr<_Ty>                    (const smart_ptr<_Ty, _Other>&);
    template<class _Other> smart_gd_simple_ptr<_Ty>&    operator =    (const smart_ptr<_Ty, _Other>&);

    template<class _Other> smart_gd_simple_ptr<_Ty>                    (const smart_gd_simple_ptr<_Other>&);
    template<class _Other> smart_gd_simple_ptr<_Ty>&    operator =    (const smart_gd_simple_ptr<_Other>&);
};

/************************************************************************/
/*                   smart_array_ptr 數(shù)組智能指針                        */
/************************************************************************/

template<class _Ty>
class smart_array_ptr : public smart_ptr<_Ty, array_deleter<_Ty>>
{
public:
    smart_array_ptr(_Ty* _Ptr = 0)                                : smart_ptr(_Ptr)    {}
    smart_array_ptr(smart_simple_ptr<_Ty>& _Right)                : smart_ptr(_Right)    {}
    smart_array_ptr(smart_ptr<_Ty, array_deleter<_Ty>>& _Right)    : smart_ptr(_Right)    {}

    smart_array_ptr<_Ty>& operator = (smart_ptr<_Ty, array_deleter<_Ty>>& _Right)
    {return (smart_array_ptr<_Ty>&)__super::operator = (_Right);}

    smart_array_ptr<_Ty>& operator = (smart_array_ptr<_Ty>& _Right)
    {return (smart_array_ptr<_Ty>&)__super::operator = (_Right);}

    smart_array_ptr<_Ty>& operator = (_Ty* _Ptr)
    {return (smart_array_ptr<_Ty>&)__super::operator = (_Ptr);}

private:
    template<class _Other> smart_array_ptr<_Ty>                    (const smart_ptr<_Ty, _Other>&);
    template<class _Other> smart_array_ptr<_Ty>&    operator =    (const smart_ptr<_Ty, _Other>&);

    template<class _Other> smart_array_ptr<_Ty>                    (const smart_array_ptr<_Other>&);
    template<class _Other> smart_array_ptr<_Ty>&    operator =    (const smart_array_ptr<_Other>&);
};

/************************************************************************/
/*          smart_gd_array_ptr 數(shù)組智能指針 (使用全局 delete)          */
/************************************************************************/

template<class _Ty>
class smart_gd_array_ptr : public smart_ptr<_Ty, global_array_deleter<_Ty>>
{
public:
    smart_gd_array_ptr(_Ty* _Ptr = 0)                                        : smart_ptr(_Ptr)    {}
    smart_gd_array_ptr(smart_gd_array_ptr<_Ty>& _Right)                        : smart_ptr(_Right)    {}
    smart_gd_array_ptr(smart_ptr<_Ty, global_array_deleter<_Ty>>& _Right)    : smart_ptr(_Right)    {}

    smart_gd_array_ptr<_Ty>& operator = (smart_ptr<_Ty, global_array_deleter<_Ty>>& _Right)
    {return (smart_gd_array_ptr<_Ty>&)__super::operator = (_Right);}

    smart_gd_array_ptr<_Ty>& operator = (smart_gd_array_ptr<_Ty>& _Right)
    {return (smart_gd_array_ptr<_Ty>&)__super::operator = (_Right);}

    smart_gd_array_ptr<_Ty>& operator = (_Ty* _Ptr)
    {return (smart_gd_array_ptr<_Ty>&)__super::operator = (_Ptr);}

private:
    template<class _Other> smart_gd_array_ptr<_Ty>                (const smart_ptr<_Ty, _Other>&);
    template<class _Other> smart_gd_array_ptr<_Ty>&    operator =    (const smart_ptr<_Ty, _Other>&);

    template<class _Other> smart_gd_array_ptr<_Ty>                (const smart_gd_array_ptr<_Other>&);
    template<class _Other> smart_gd_array_ptr<_Ty>&    operator =    (const smart_gd_array_ptr<_Other>&);
};


 --------------------------------------------------------------------------------

 后記

• 對(duì)于內(nèi)存管理,其實(shí)還有一種情形還沒(méi)講的,就是如何優(yōu)雅地管理 vetor、list、map 這類容器中的指針,這個(gè)話題留到以后討論 STL 時(shí)再詳細(xì)闡述吧。
•在本座的代碼中基本上看不到 free / delere 這類單詞(new 則是有的 —— 給智能指針賦值的時(shí)候 ^_^),就本座的經(jīng)驗(yàn)而言,封裝如果利用得當(dāng)確實(shí)能減少很多麻煩,使代碼更清晰,有條理,降低錯(cuò)誤發(fā)生幾率。
•當(dāng)然了,封裝并不是萬(wàn)能,它不能解決所有問(wèn)題,關(guān)鍵是靠個(gè)人的專注與細(xì)心。
•本座碼字提出自己的觀點(diǎn),旨在拋磚引玉,激發(fā)大家思考如何培養(yǎng)良好的編程習(xí)慣,不是權(quán)威,更不能盡信。最實(shí)在的知識(shí)應(yīng)該來(lái)自個(gè)人最直接的體驗(yàn)。

相關(guān)文章

最新評(píng)論