c 教學 C C 陣列名與指標區別深入探索

2021-05-01 10:44:55 字數 3828 閱讀 6395

程式設計學習-二維字串陣列的初始化-動態記憶體分配

動態記憶體分配

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本身並沒有撤銷,它自己仍然存在,該指標所佔記憶體空間並未釋放。

4. 在堆中建立動態一維陣列

①申請陣列空間:

指標變數名=new 型別名[下標表示式];

注意:「下標表示式」不是常量表示式,即它的值不必在編譯時確定,可以在執行時確定。

②釋放陣列空間:

delete [ ]指向該陣列的指標變數名;

注意:方括號非常重要的,如果delete語句中少了方括號,因編譯器認為該指標是指向陣列第乙個元

素的,會產生**不徹底的問題(只**了第乙個元素所佔空間),加了方括號後就轉化為指向陣列

的指標,**整個陣列。delete [ ]的方括號中不需要填陣列元素數,系統自知。即使寫了,編譯器

也忽略。

#include

#include

void main()

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]……;

例如:建立loat (*cp)[30][20] ; //指向乙個30行20列陣列的指標,指向二維陣列的指標

cp=new float [15] [30] [20];    //建立由15個30*20陣列組成的陣列;

注意:cp等效於三維陣列名,但沒有指出其邊界,即最高維的元素數量,就像指向字元的指標即等效

乙個字串,不要把指向字元的指標,說成指向字串的指標。這與陣列的巢狀定義相一致。

總結如下方法:

指標對應關係為

char *a[6]<=>char **a      //在函式傳遞引數時候很容易出錯

char a[5][6]<=>char (*a)[6]

int a[50][100];

int *p=&a[0][0];

a[i][j]<=>*(p+100*i+j);

或:int (*p)[100];  

p=a;

a[i][i]<=>*(*(p+i)+j);

char *a[10];       //指標陣列

for (i=0;i<10;i++)

a[i]=new char[10];

for(i=0;i<10;i++)

delete a[i];

#include

#include

int main()

C C 陣列名與指標區別深入探索

引言 指標是c c 語言的特色,而陣列名與指標有太多的相似,甚至很多時候,陣列名可以作為指標使用。於是乎,很多程式設計者就被搞糊塗了。而許多的大學老師,他們在c語言的教學過程中也錯誤得給學生講解 陣列名就是指標 很幸運,我的大學老師就是其中之一。時至今日,我日復一日地進行著c c 專案的開發,而身邊...

C C 陣列名與指標區別深入探索

引言 指標是c c 語言的特色,而陣列名與指標有太多的相似,甚至很多時候,陣列名可以作為指標使用。於是乎,很多程式設計 者就被搞糊塗了。而許多的大學老師,他們在c語言的教學過程中也錯誤得給學生講解 陣列名就是指標 很幸運,我的大學老師就是其中之一。時至今日,我日復一日地進行著c c 專案的開發 而身...

C C 陣列名與指標區別深入探索

引言 指標是c c 語言的特色,而陣列名與指標有太多的相似,甚至很多時候,陣列名可以作為指標使用。於是乎,很多程式設計 者就被搞糊塗了。而許多的大學老師,他們在c語言的教學過程中也錯誤得給學生講解 陣列名就是指標 很幸運,我的大學老師就是其中之一。時至今日,我日復一日地進行著c c 專案的開發 而身...