動態記憶體分配(詳解)

來源:互聯網
上載者:User

轉自:http://hi.baidu.com/xiaomeng008/item/f0a4d6f59d65532b743c4c86

動態記憶體分配
1.堆記憶體配置 :
C/C++定義了4個記憶體區間:代碼區,全域變數與靜態變數區,局部變數區即棧區,動態儲存裝置區,即堆(heap)區或自由儲存區(free store)。

堆的概念:
通常定義變數(或對象),編譯器在編譯時間都可以根據該變數(或對象)的類型知道所需記憶體空間的大小,從而系統在適當的時候為他們分配確定的儲存空間。這種記憶體配置稱為靜態儲存分配;
有些操作對象只在程式運行時才能確定,這樣編譯時間就無法為他們預定儲存空間,只能在程式運行時,系統根據運行時的要求進行記憶體配置,這種方法稱為動態儲存裝置分配。所有動態儲存裝置分配都在堆區中進行。
當程式運行到需要一個動態分配的變數或對象時,必須向系統申請取得堆中的一塊所需大小的存貯空間,用於存貯該變數或對象。當不再使用該變數或對象時,也就是它的生命結束時,要顯式釋放它所佔用的存貯空間,這樣系統就能對該堆空間進行再次分配,做到重複使用有限的資源。

2.堆記憶體的分配與釋放
堆空間申請、釋放的方法:
在C++中,申請和釋放堆中分配的存貯空間,分別使用new和delete的兩個運算子來完成:    
指標變數名=new 類型名(初始化式);
    delete 指標名;
例如:
1、 int *pi=new int(0);
它與下列代碼序列大體等價:
2、int ival=0, *pi=&ival;

區別:pi所指向的變數是由庫操作符new()分配的,位於程式的堆區中,並且該對象未命名。  

堆空間申請、釋放說明:
⑴.new運算子返回的是一個指向所配置類型變數(對象)的指標。對所建立的變數或對象,都是通過該指標來間接操作的,而且動態建立的對象本身沒有名字。
⑵.一般定義變數和對象時要用標識符命名,稱命名物件,而動態稱無名對象(請注意與棧區中的臨時對象的區別,兩者完全不同:生命期不同,操作方法不同,臨時變數對程式員是透明的)。
⑶.堆區是不會在分配時做自動初始化的(包括清零),所以必須用初始化式(initializer)來顯式初始化。new運算式的操作序列如下:從堆區指派至,然後用括弧中的值初始化該對象。

3.堆空間申請、釋放示範:
⑴.用初始化式(initializer)來顯式初始化 
int *pi=new int(0);
⑵.當pi生命週期結束時,必須釋放pi所指向的目標:
delete pi;

注意這時釋放了pi所指的目標的記憶體空間,也就是撤銷了該目標,稱動態記憶體釋放(dynamic memory deallocation),但指標pi本身並沒有撤銷,它自己仍然存在,該指標所佔記憶體空間並未釋放。 

下面是關於new 操作的說明 
⑴.new運算子返回的是一個指向所配置類型變數(對象)的指標。對所建立的變數或對象,都是通過該指標來間接操作的,而動態建立的對象本身沒有名字。 
⑵.一般定義變數和對象時要用標識符命名,稱命名物件,而動態稱無名對象(請注意與棧區中的臨時對象的區別,兩者完全不同:生命期不同,操作方法不同,臨時變數對程式員是透明的)。 
⑶.堆區是不會在分配時做自動初始化的(包括清零),所以必須用初始化式(initializer)來顯式初始化。new運算式的操作序列如下:從堆區指派至,然後用括弧中的值初始化該對象。

4. 在堆中建立動態一維數組
①申請數組空間:
指標變數名=new 類型名[下標運算式];
注意:“下標運算式”不是常量運算式,即它的值不必在編譯時間確定,可以在運行時確定。

②釋放數組空間:
delete [ ]指向該數組的指標變數名;

注意:方括弧非常重要的,如果delete語句中少了方括弧,因編譯器認為該指標是指向數組第一個元素的,會產生回收不徹底的問題(只回收了第一個元素所佔空間),加了方括弧後就轉化為指向數組的指標,回收整個數組。delete [ ]的方括弧中不需要填數組元素數,系統自知。即使寫了,編譯器也忽略。
#include <iostream.h>
#include <string.h>
void main(){
     int n;
     char *pc;
     cout<<"請輸入動態數組的元素個數"<<endl;
     cin>>n; //n在運行時確定,可輸入17
     pc=new char[n]; //申請17個字元(可裝8個漢字和一個結束符)的記憶體空間
     strcpy(pc,“堆記憶體的動態分配”);//
     cout<<pc<<endl;
     delete []pc;//釋放pc所指向的n個字元的記憶體空間
     return ;
}


5. 動態一維數組的說明
① 變數n在編譯時間沒有確定的值,而是在運行中輸入,按運行時所需分配堆空間,這一點是動態分配的優點,可克服數組“大開小用”的弊端,在表、排序與尋找中的演算法,若用動態數組,通用性更佳。一定注意:delete []pc是將n個字元的空間釋放,而用delete pc則只釋放了一個字元的空間;
② 如果有一個char *pc1,令pc1=p,同樣可用delete [] pc1來釋放該空間。儘管C++不對數組作邊界檢查,但在堆空間分配時,對數組分配空間大小是紀錄在案的。
③ 沒有初始化式(initializer),不可對數組初始化。 

6.指標數組和數組指標
指標類型:
(1)int*ptr;//指標所指向的類型是int 
(2)char*ptr;//指標所指向的的類型是char 
(3)int**ptr;//指標所指向的的類型是int* (也就是一個int * 型指標) 
(4)int(*ptr)[3];//指標所指向的的類型是int()[3] //二維指標的聲明

指標數組:
一個數組裡存放的都是同一個類型的指標,通常我們把他叫做指標數組。 
比如 int * a[2];它裡邊放了2個int * 型變數 .
int * a[2]; 
a[0]= new int[3]; 
a[1]=new int[3]; 
delete a[0]; 
delete a[1]; 
注意這裡 是一個數組,不能delete [] ; 

數組指標:
一個指向一維或者多維陣列的指標.
int * b=new int[10]; 指向一維數組的指標b ; 
注意,這個時候釋放空間一定要delete [] ,否則會造成記憶體泄露, b 就成為了空懸指標 

int (*b2)[10]=new int[10][10]; 注意,這裡的b2指向了一個二維int型數組的首地址. 
注意:在這裡,b2等效於二維數組名,但沒有指出其邊界,即最高維的元素數量,但是它的最低維數的元素數量必須要指定!就像指向字元的指標,即等效一個字串,不要把指向字元的指標說成指向字串的指標。
int(*b3) [30] [20]; //三級指標――>指向三維數組的指標; 
int(*b2) [20];     //二級指標;――>指向二維數組的指標; 
b3=new int [1] [20] [30]; 
b2=new int [30] [20]; 
刪除這兩個動態數組可用下式: 
delete [] b3; //刪除(釋放)三維數組; 
delete [] b2; //刪除(釋放)二維數組;

在堆中建立動態多維陣列
new 類型名[下標運算式1] [下標運算式2]……;

例如:建立一個動態三維數組
float (*cp)[30][20] ; //指向一個30行20列數組的指標,指向二維數組的指標
cp=new float [15] [30] [20]; //建立由15個30*20數組組成的數組;

注意:cp等效於三維數組名,但沒有指出其邊界,即最高維的元素數量,就像指向字元的指標即等效一個字串,不要把指向字元的指標,說成指向字串的指標。這與數組的嵌套定義相一致。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.