1. 程式人生 > >C++動態二維陣列記憶體的分配和釋放 opencv

C++動態二維陣列記憶體的分配和釋放 opencv

二維陣列動態陣列分配和釋放
首先,陣列指標和指標陣列的區別:
<p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="color: rgb(0, 0, 255);">指標陣列:</span>array of pointers,即用於儲存指標的陣列,也就是陣列元素都是指標,指標的陣列</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="color: rgb(0, 0, 255);">陣列指標:</span>a pointer to an array,即指向陣列的指標,陣列的指標</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">用法的區別:</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">int* a[4]     指標陣列     指標的陣列</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">                 表示:陣列a中的元素都為int型指標    </p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="color: rgb(255, 0, 0);">                 元素表示:*a[i]   *(a[i])是一樣的,因為[]優先順序高於*</span></p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">int (*a)[4]   陣列指標    陣列的指標 </p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">                 表示:指向陣列a的指標</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="color: rgb(255, 0, 0);">                 元素表示:(*a)[i]  </span></p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 18px;">類似的還有指標函式和函式指標,以後再說</span>
</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;">然後,new 的用法 C++</p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="color: rgb(51, 51, 51); font-family: Helvetica, arial, freesans, clean, sans-serif; line-height: 23.799999237060547px; background-color: rgb(240, 240, 240);">和 sizeof 類似,new 和 delete 不是函式,它們都是 C++ 定義的關鍵字,通過特定的語法可以組成表示式。和 sizeof 不同的是,sizeof 在編譯時候就可以確定其返回值,new 和 delete 背後的機制則比較複雜。</span></p><p style="line-height: 18px; background-color: rgb(255, 255, 255); margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif;"><span style="color: rgb(51, 51, 51); font-family: Helvetica, arial, freesans, clean, sans-serif; line-height: 23.799999237060547px; background-color: rgb(240, 240, 240);">new 和 C 語言中的 malloc 函式一樣,用來動態申請空間的。</span></p><p style="margin: 10px auto;"><span style="font-family:Helvetica, arial, freesans, clean, sans-serif;color:#333333;"><span style="line-height: 23.799999237060547px;">C 語言中     </span></span><span style="color: rgb(51, 51, 51); font-family: arial, 'courier new', courier, 宋體, monospace, 'Microsoft YaHei'; line-height: 24px;">void *malloc(int size);</span></p><p style="margin: 10px auto;"><span style="font-family:Helvetica, arial, freesans, clean, sans-serif;color:#333333;"><span style="line-height: 23.799999237060547px;"></span></span><pre id="recommend-content-19539850" accuse="aContent" class="recommend-text mb-10" style="margin-top: 0px; margin-bottom: 10px; padding: 0px; font-family: arial, 'courier new', courier, 宋體, monospace, 'Microsoft YaHei'; white-space: pre-wrap; word-wrap: break-word; font-size: 14px; color: rgb(51, 51, 51); line-height: 24px; background-color: rgb(243, 255, 236);">說明:malloc 向系統申請分配指定size個位元組的記憶體空間。返回型別是 void* 型別。void* 表示未確定型別的指標。
C,C++規定,void* 型別可以強制轉換為任何其它型別的指標。
從函式宣告上可以看出。malloc 和 new 至少有兩個不同: new 返回指定型別的指標,並且可以自動計算所需要大小。
用free( ) 釋放記憶體

void *malloc(long NumBytes):該函式分配了NumBytes個位元組,並返回了指向這塊記憶體的指標。如果分配失敗,則返回一個空指標(NULL)。

關於分配失敗的原因,應該有多種,比如說空間不足就是一種。

void free(void *FirstByte): 該函式是將之前用malloc分配的空間還給程式或者是作業系統,也就是釋放了這塊記憶體,讓它重新得到自由。

C++中,new 用 delete 釋放。

new int;//開闢一個存放整數的儲存空間,返回一個指向該儲存空間的地址(即指標) 

new int(100);//開闢一個存放整數的空間,並指定該整數的初值為100,返回一個指向該儲存空間的地址 

new char[10];//開闢一個存放字元陣列(包括10個元素)的空間,返回首元素的地址 

new int[5][4];//開闢一個存放二維整型陣列(大小為5*4)的空間,返回首元素的地址

float *p=new float (3.14159);//開闢一個存放單精度數的空間,並指定該實數的初值為//3.14159,將返回的該空間的地址賦給指標變數p   

new運算子使用的一般格式為   new 型別 [初值]   
用new分配陣列空間時不能指定初值。
如果由於記憶體不足等原因而無法正常分配空間,則new會返回一個空指標NULL,使用者可以根據該指標的值判斷分配空間是否成功。  
 delete運算子使用的一般格式為   delete [ ] 指標變數   
例如要撤銷上面用new開闢的存放單精度數的空間(上面第5個例子),應該用   delete p;   
前面用“new char[10];”開闢的字元陣列空間,如果把new返回的指標賦給了指標變數pt,則應該用以下形式的delete運算子撤銷該空間:   
        delete [] pt;//在指標變數前面加一對方括號,表示是對陣列空間的操作   

<span style="background-color: rgb(240, 240, 240); font-family: Arial, Helvetica, sans-serif;">第一種:陣列指標的記憶體分配和釋放</span>
1、
char (*p)[N];//指向陣列的指標
p = new char[M][N];
/*分配一個含有M*N個元素的二位陣列,未被初始化*/
delete[] p; 
/*釋放記憶體*/
2、
char **p;//<span style="background-color: rgb(240, 240, 240); color: rgb(51, 51, 51); font-family: arial, 'courier new', courier, 宋體, monospace, 'Microsoft YaHei'; line-height: 24px;">雙重指標,<span style="font-family: arial; font-size: 13px; line-height: 20.020000457763672px;">指向</span><span style="color: rgb(204, 0, 0); font-family: arial; font-size: 13px; line-height: 20.020000457763672px;">int</span><span style="color: rgb(51, 51, 51); font-family: arial; font-size: 13px; line-height: 20.020000457763672px;">型別指標的指標,所以p的型別為一個指向整形的指標</span></span>
p = new char* [M];//分配指標陣列
for(int i=0; i<M; i++)
    p[i] = new char[N];//分配每個指標所指向的陣列
for(i=0; i<M; i++)
    delete[] p[i];
delete[] p; 
第二種,指標陣列的記憶體分配和釋放
1、如上,指標的陣列
char **p;
p= new char* [M];
p[0] = new char[M *N];//一次性分配所有空間
for(int i=1; i<M; i++)
    p[i] = p[i-1] + N;//分配每個指標所指向的陣列
delete[] p[0];
delete[] p; 
2、
char* P[M];//指標的陣列
for(int i=0; i<M; i++)
   P[i] = new char[N];  //分配每個指標的空間
for(i=0; i<M; i++)
   delete[] P[i]; 
3、
char* a[M];//指標的陣列
a[0] = new char[M*n];<span style="background-color: rgb(240, 240, 240); font-family: Arial, Helvetica, sans-serif;">//分配每個指標的空間</span>
for(int i=1; i<M; i++)
    a[i] = a[i-1] + n;<span style="background-color: rgb(240, 240, 240); font-family: Arial, Helvetica, sans-serif;">//分配每個指標所指向的陣列</span>
delete[] a[0]; 

注意:

為了避免記憶體洩漏,new和delete要注意配對使用,即有多少個new就有多少個delete

何為記憶體洩漏?

answer:

記憶體洩漏也稱作“儲存滲漏”,用動態儲存分配函式動態開闢的空間,在使用完畢後未釋放,結果導致一直佔據該記憶體單元。直到程式結束。(其實說白了就是該記憶體空間使用完畢之後未回收)即所謂記憶體洩漏。

記憶體洩漏形象的比喻是“作業系統可提供給所有程序的儲存空間正在被某個程序榨乾”,最終結果是程式執行時間越長,佔用儲存空間越來越多,最終用盡全部儲存空間,整個系統崩潰。所以“記憶體洩漏”是從作業系統的角度來看的。這裡的儲存空間並不是指實體記憶體,而是指虛擬記憶體大小,這個虛擬記憶體大小取決於磁碟交換區設定的大小。由程式申請的一塊記憶體,如果沒有任何一個指標指向它,那麼這塊記憶體就洩漏了。

危害變現:

記憶體洩漏或者是說,資源耗盡後,系統會表現出什麼現象啊? cpu資源耗盡:估計是機器沒有反應了,鍵盤,滑鼠,以及網路等等。這個在windows上經常看見,特別是中了毒。 程序id耗盡:沒法建立新的程序了,串列埠或者telnet都沒法建立了。 硬碟耗盡: 機器要死了,交換記憶體沒法用,日誌也沒法用了,死是很正常的。 記憶體洩漏或者記憶體耗盡:新的連線無法建立,free的記憶體比較少。發生記憶體洩漏的程式很多,但是要想產生一定的後果,就需要這個程序是無限迴圈的,是個服務程序。當然,核心也是無限迴圈的,所以,如果核心發生了記憶體洩漏,情況就更加不妙。記憶體洩漏是一種很難定位和跟蹤的錯誤,目前還沒看到有什麼好用的工具(當然,使用者空間有一些工具,有靜態分析的,也會動態分析的,但是找核心的記憶體洩漏,沒有好的開源工具)。 記憶體洩漏和物件的引用計數有很大的關係,再加上c/c++都沒有自動的垃圾回收機制,如果沒有手動釋放記憶體,問題就會出現。如果要避免這個問題,還是要從程式碼上入手,良好的編碼習慣和規範,是避免錯誤的不二法門。 一般我們常說的記憶體洩漏是指堆記憶體的洩漏。 堆記憶體是指程式從堆中分配的,大小任意的(記憶體塊的大小可以在程式執行期決定),使用完後必須顯式釋放的記憶體。 應用程式一般使用malloc,realloc,new等函式從堆中分配到一塊記憶體,使用完後,程式必須負責相應的呼叫free或delete釋放該記憶體塊,否則,這塊記憶體就不能被再次使用,我們就說這塊記憶體洩漏了。 OK ,that`s all.