亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

詳解C++編程習慣之內存管理的應用

2020-02-24 14:31:30
字體:
來源:轉載
供稿:網友

我們在平常的工作中積累了一些知識,隨著我們知識的擴展和水平的提高,你一定會發現原來的知識儲備是片面的、有限的,下文是武林技術頻道小編分享的詳解C++編程習慣之內存管理的應用,一起來看看吧!

開篇導讀???     

  雖然本系列文章定位為科普讀物,但本座相信它們不但適合新手們學習借鑒,同時也能引發老鳥們的反思與共鳴。歡迎大家提出寶貴的意見和反饋 ^_^

  在開篇講述本章主要內容之前,本座首先用小小篇幅論述一下一種良好的工作習慣 —— 積累、提煉與求精。在工作和學習的過程中,不斷把學到的知識通過有效的方式積累起來,形成自己的知識庫,隨著知識量的擴大,就會得到從量變到質變的提升。這時,就需要你有精益求精精的態度和毅力對知識庫進行優化整理。

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

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

內存管理相關問題

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

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

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

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

?內存映射文件

  下面的代碼把 File Mapping 句柄以及從 File Mapping 映射出來的內存分別封裝到 CFileMapping 和 CShareMemory 中,可以直接使用 CShareMemory 可以創建一個 File Mapping 以及映射 File Mapping 的內存。

?

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)
};


?

?

  細心的朋友一定會發覺其實這樣封裝是有缺點的:首先,CShareMemory 只能做內存共享,不能映射到真實文件(hFile 永遠為 INVALID_HANDLE_VALUE);第二,可以對 CShareMemory 的 Alloc() 和 Free() 方法進一步封裝,利用封裝類的析構函數自動調用 Free(),這樣就可以完全消除 “set<ULONG_PTR> m_set” 這個屬性了;第三,CFileMapping 也可以把文件句柄一起封裝進來,這樣,從 CreateFile() 到 CreateFileMapping() 都受控了。這個不完美的封裝就權當反面教材吧 ^_^

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

malloc() 系列函數

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

?

// T???????????????? : 數據類型(內置類型或結構體)
// MAX_CACHE_SIZE??? : 預申請內存的最大數目,以 sizeof(T) 為單位,如果該值設置合理,對于
//???????????????????? 需要動態遞增緩沖區的 buffer 來說能大大提高效率
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);}
??? // 拷貝構造函數要分兩種情形
??? 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;
??? }

??? // 動態擴大 buffer
??? template<size_t S> CBufferPtrT& Cat(const CBufferPtrT<T, S>& other)
??? {
??????? if((void*)&other != (void*)this)
??????????? Cat(other.Ptr(), other.Size());

??????? return *this;
??? }

??? // 動態擴大 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();}
??? // 哇塞,竟然還支持索引訪問
??? 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

?

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

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

?

測試用例
?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;

???? // 下面這行編譯不通過,正好說明這個類是類型安全的
?// bufferI = bufferS;

???? return 0;
?}

?


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

?

?

new & delete

  一說到 new 的封裝大家立馬想到的就是智能指針吧!沒錯,就是智能指針。但 STL 提供的 auto_ptr 缺陷很多,首先使用起來不方便,竟然連這種寫法都不支持:“std::auto_ptr<int> pi = new int;”,天理何在??!更可恨的是不支持數組指針(需要 delete[]),另外如果某些類重載了 new 操作符的話使用它也有很多問題的,還有其它的很多缺點(我忘記了 ^_^)。不過,C++0x 似乎對智能指針作了重大改進,已經有支持引用計數的智能指針了,但不知是否解決數組指針和區分 delete 與 ::delete 的問題(本座沒實測,要是您知道麻煩告訴一聲 ^_^)。無論如何,下面代碼列出的智能指針支持區分 delete / delete[] / ::delete / ::delete[]。算是 auto_ptr 的改良(也沒有使用引用計數),文章篇幅太長了,測試用例就不發了,各位看官自行嘗試吧:

?

/************************************************************************/
/*?????????????????????? smart_ptr 單實體或數組智能指針??????????????????? */
/************************************************************************/

?

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 單實體智能指針????????????????????? */
/************************************************************************/

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 單實體智能指針 (使用全局 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 數組智能指針??????????????????????? */
/************************************************************************/

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 數組智能指針 (使用全局 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>&);
};


?--------------------------------------------------------------------------------

?后記

?

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

以上就是給武林技術頻道小編給大家述說的詳解C++編程習慣之內存管理的應用,如果有筒靴們對這行業有興趣的話,可以在這方面進行深入學習。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩中文字幕在线| 亚洲天堂av高清| 亚洲成人黄色网址| 日韩免费av片在线观看| 日韩电影中文字幕一区| 中文字幕亚洲字幕| 在线性视频日韩欧美| 中文字幕久热精品视频在线| 亚洲精品成人久久久| 精品国产老师黑色丝袜高跟鞋| 成人中心免费视频| 黄色成人在线免费| 在线看日韩欧美| 欧美激情在线观看| 国产做受高潮69| 久久久亚洲福利精品午夜| 夜夜嗨av一区二区三区四区| 亚洲国产三级网| 91爱视频在线| 自拍亚洲一区欧美另类| 欧美精品电影在线| 亚洲成人教育av| 国产精品久久久久久婷婷天堂| 欧美成人精品三级在线观看| 羞羞色国产精品| 色综合老司机第九色激情| 国产最新精品视频| 成人伊人精品色xxxx视频| 姬川优奈aav一区二区| 亚洲裸体xxxx| 欧美孕妇毛茸茸xxxx| 亚洲国产精品久久久久久| 久久久久久久久久久久久久久久久久av| 国产精品一区二区久久久| 538国产精品一区二区免费视频| 国产视频欧美视频| 亚洲欧美日韩成人| 久久天天躁狠狠躁夜夜躁| 久久国产精品影视| 4k岛国日韩精品**专区| 国产99视频在线观看| 奇米成人av国产一区二区三区| 97精品一区二区视频在线观看| 精品少妇一区二区30p| 中文国产成人精品久久一| 国产亚洲精品久久久| 国产成人精品久久二区二区91| 欧美色视频日本版| 成人a视频在线观看| 97在线视频国产| 国产偷国产偷亚洲清高网站| 欧美色videos| 亚洲美女视频网| 亚洲精品xxxx| 亚洲欧美国产日韩中文字幕| 亚洲成色777777女色窝| 欧美亚洲国产成人精品| 欧美人在线观看| 亚洲自拍中文字幕| 4k岛国日韩精品**专区| 日韩国产欧美精品一区二区三区| 成人情趣片在线观看免费| 成人免费看吃奶视频网站| 92国产精品久久久久首页| 欧美激情视频给我| 精品呦交小u女在线| 亚洲一区二区日本| 久久影院在线观看| 97视频在线播放| 国产精品自产拍在线观看中文| 91中文字幕在线| 亚洲欧美成人在线| 91久久精品国产91性色| 精品国产依人香蕉在线精品| 岛国视频午夜一区免费在线观看| 国产欧美精品日韩| 精品国产自在精品国产浪潮| 国产在线视频不卡| 欧美性在线观看| 欧美性xxxx| 久久久人成影片一区二区三区| 亚洲国产91精品在线观看| 欧美性黄网官网| 亚洲色图校园春色| 91啪国产在线| 欧美视频第一页| 欧美一区二区大胆人体摄影专业网站| 久久亚洲欧美日韩精品专区| 少妇av一区二区三区| 久久久久久18| 91美女高潮出水| 国产热re99久久6国产精品| 黄色成人av网| 成人激情春色网| 色噜噜狠狠狠综合曰曰曰88av| 性日韩欧美在线视频| 亚洲人成人99网站| 久久99国产精品自在自在app| 国内伊人久久久久久网站视频| 91久久国产综合久久91精品网站| 久久久久中文字幕2018| 永久免费毛片在线播放不卡| 中文字幕亚洲色图| 欧美放荡办公室videos4k| 久久久国产一区二区三区| 国产精品福利网| 91精品国产91久久久久| 久久久国产一区二区三区| 国产精品色午夜在线观看| 亚洲国产欧美在线成人app| 国产成人免费av| 欧美影院成年免费版| 色婷婷综合成人av| 久久国产精品网站| 国产一区二区三区在线| 成人春色激情网| 亚洲欧美激情一区| 国产欧美中文字幕| 中文日韩电影网站| 欧美大肥婆大肥bbbbb| 亚洲另类图片色| 欧美成人精品在线播放| 91九色单男在线观看| 91久久在线观看| 欧美亚洲午夜视频在线观看| 欧美精品videossex88| 成人性生交大片免费看视频直播| 国产精品丝袜一区二区三区| 亚洲欧美日韩爽爽影院| 日韩视频在线免费观看| 日韩人在线观看| 欧美体内谢she精2性欧美| 奇门遁甲1982国语版免费观看高清| 一本色道久久综合狠狠躁篇怎么玩| 日韩在线观看免费| 国产成人激情视频| 精品福利在线视频| 九九热精品视频国产| 午夜精品美女自拍福到在线| 午夜精品视频网站| 欧美电影在线播放| 欧美成人四级hd版| 中文字幕视频一区二区在线有码| 成人欧美一区二区三区在线湿哒哒| 亚洲国产天堂网精品网站| 亚洲国产日韩精品在线| 最新国产精品拍自在线播放| 精品国产欧美一区二区五十路| 欧美日韩国产va另类| 国产精品欧美亚洲777777| 久久综合亚洲社区| 国产精品中文字幕在线| 欧洲永久精品大片ww免费漫画| 国模视频一区二区三区| 亚洲男人的天堂网站| 黄色成人av在线| 中文字幕一区二区三区电影| 久久久久北条麻妃免费看| 97免费视频在线| 91精品在线影院| 国产日韩中文在线| 国产日韩欧美91| 97色伦亚洲国产| 国产欧美久久一区二区|