Array 與 Pointer Array Dynamical Memory Allocation Array( 陣列 ) 陣列是用來存放同樣型態的資料陣列的大小必須在程式中預先設定在程式執行中, 陣列的大小無法改變陣列中的資料是透過索引 (index) 來存取
一維陣列的宣告 type array_name[array_size]; int iarray[100]; /* an integer array with 100 elements */ 7 51 22 43 9 0 1 2 98 99 char carray[25]; /* a character array with 25 elements */ float farray[10]; /* a floating-number array with 10 elements */ 一維陣列的資料存取 array_variable_name[index] int iarray[100]; 7 51 22 43 9 0 1 2 98 99 存 iarray[k] = 50; /* 將 50 存入索引 k 所指的位置 */ 取 int temp; temp = iarray[k]; /* 將 k 所指位置中的資料值存入變數 temp 內 */
一維陣列和記憶體間的對應 Memory m m + 2 m + 4 m + int iarray[100]; 7 51 22 43 9 m + 198 0 1 2 98 99 假定 sizeof(int) = 2 多維陣列的宣告 type array_name[arraysize 1 ]... [arraysize[ n ]; int mesh[7][11]; float cube[][8][3]; 5 4 3 2 1 0 0 1 2 3 4 5 7 8 9 10 5 4 3 2 1 0 0 1 2 0 1 2 3 4 5 7
多維陣列的資料存取 int mesh[7][11]; mesh[4][2] 5 4 3 2 1 0 0 1 2 3 4 5 7 8 9 10 mesh[2][7] 多維陣列和記憶體間的對應 Memory m 5 4 3 2 1 0 0 1 2 3 4 5 7 8 9 10 int mesh[7][11]; mesh[i][j] = mesh +11 i + j 假定 sizeof(int) = 2 m + 22 m + 44 m + m + 88 m + 110 m + 132
m m + 48 5 4 m + 9 m + 144 3 2 1 0 0 1 2 3 4 5 7 0 1 2 m + 192 m + 240 m + 288 float cube[][8][3]; cube[i][j][k] = cube + 24i + 8j+ k 假定 sizeof(int) = 2 Dynamical Memory Allocation 資料變數與指標變數 指標變數的宣告 位址運算子 & 利用指標來間接存取資料 動態配置的運算子 new 和 delete
我們稱直接存放資料值的變數為 資料變數 (data variable) 變數 i 儲存一個整數資料值 int i; 變數 c 儲存一個字元資料值 char c; 變數 f 儲存一個實數資料值 float f; 變數 p 儲存一個由兩個整數組成的結構資料值 struct point2dtype { int x, y; }; point2dtype P; p i c f x y heap 100 101 102 103 104 105 10 107 108 109 110 111 112 113 114 115 11 117 若一個變數存放的是位址而非實際的資料值, 則該變數稱為 指標變數 (pointer variable), 或簡稱為 指標 (pointer) Look in location 344 for what you want 344 pointer p 2 10 5 9 340 344 348 352 35
指標的宣告 type_name *pointer_name; 宣告變數 pointer_name 為指標變數, 且其所指的位址是用來存放型態為 type_name 的資料值 int *iptr; iptr 是整數指標變數, 其指的位址所存放的資料值將被視為整數值 char *cptr; cptr 是字元指標變數, 其指的位址所存放的資料值將被視為字元值 float *fptr; fptr 是實數指標變數, 其指的位址所存放的資料值將被視為實數值 point2dtype *pptr; pptr 是指標變數, 其指的位址所存放的資料值將被視為 PointType 值 int *p, q; p 是整數指標變數, 而 q 是整數變數 此宣告相當於底下的宣告 : int *p; int q;
如果想將 p 和 q 均宣告為指標, 則必須用下列宣告 : int *p, *q; 或者是 : typedef int* intptrtype; intptrtype p, q; address-of operator( 位址運算子 ) &variable_name 位址運算元是用來求取變數的記憶體位址 上式的值是變數 variable_name 的位址 int i, *; i = ; 將變數 i 的位址存入指標 中 = &i; i i 存著 i 的位址 i
= i /* error */ = 100; /* error */ OK, 存放記憶體絕對位址 100 = (int *) 100 或 = reinterpret_cast<int *>(100); 100 i 利用指標來間接存取資料值 : *pointer_name * : indirection or dereferencing operator. 此式的值是指標 pointer_name 所指記憶體位址中的資料值 int i, *; i = ; 將變數 i 的位址存入指標 中 = &i; i i i or *
* = 7; 和 i = 7 效果一樣 7 i or * * = * + 1; 和 i = i + 1 效果一樣 8 i or * 注意!!! int *; /* 宣告 是一個整數指標變數 */ * = 100; /* 將 100 存入指標 所指的位址中 */ Dynamic Allocation( 動態配置 ) 如前所述, 電腦將編譯後的可執行程式載入記憶體時, 會先在記憶體中的資料區 (heap) 中預留一些空間給全域變數 (global variables) 以儲存其資料 此類配置的方式稱為 靜態配置(static allocation) ; 這類的變數稱為 靜態配置的變數 (statically allocated variables) 如果所需的記憶體是在程式執行時才配置的, 則稱之為 動態配置 (dynamic allocation) ; 這類的變數稱為 動態配置的變數 (dynamically allocated variables) 同時, 這些變數並沒有名稱, 而必須倚靠指標來間接存取其中的資料值
new 運算子 C++ 的 new 運算子是用來動態配置一塊記憶體位址給指標變數 它有以下三種格式 : new type 配置一塊型態 type 所需大小的記憶體 new type(initial_value) 配置一塊型態 type 所需大小的記憶體, 並將其值設定成 initial_value 的值 new type [size] 配置一個陣列, 其中具有 size 個型態為 type 的元素 * int * =new int (1024); 1024 動態配置一塊記憶體來儲存一個整數資料, 將其值設為 1024, 然後將此記憶體的位址存入指標變數 中 float *fp =new float (1.0); fp 1.0 *fp 動態配置一塊記憶體來儲存浮點數資料, 將其值設為 1.0, 並將此記憶體的位址存入指標變數 fp 中 typedef struct { int x, y; } point; pp x y point *pp = new point; *pp 動態配置一塊記憶體來儲存 point 型態的資料, 並將此記憶體的位址存入指標變數 pp 中
int *iarray = new int [100]; 動態配置一塊記憶體來儲存 100 個整數資料, 並將此記憶體的位址存入指標變數 iarray 中 iarray 0 1 98 99 delete 運算子 C++ 的 delete 運算子是用來解除一塊經由 new 運算子配置而得的記憶體區塊, 並將之歸還給系統 它有以下兩種格式 : delete pointer; delete [] block_pointer; int * = new int; int *iarray = new int[100]; delete ; delete [] iarray;
int * P, *Q; int X; P Q X P = &X; *P = ; P = new int(0); *P = 7; P X or *P P X or *P 0 P *P X 7 P *P X Q = P; P Q 7 *P or *Q X Q = new int(8); P 7 *P X Q 8 *Q P = NULL; P 7 Q 8 *Q X delete Q ; Q = NULL; P Q 7 X memory leak
假定 P 和 Q 兩個指標指向同一塊動態配置的記憶體位址 ( 如下圖所示 ) Q = P; P Q 7 *P or *Q 試問執行 delete P; *Q = 10; 之後, 結果如何 ANS: 當執行 *Q = 10 時, 因為其所指的記憶體已歸還系統不屬於程式所有, 因而通常會引起執行錯誤 指標和陣列 int iarray[100]; int *iptr = new int [100]; iarray 和 iptr 都是含有 100 個整數的陣列 兩者都可以 用 index 的方式來存取其中的元素, 比方說 : iarray[50] 和 iptr[50] 分別代表 iarray 和 iptr 中的第 51 個整數 兩者的區別在 於 iarray 是以靜態配置的方式產生, 而 iptr 是以動態配置 的方式產生 因此,iArray 無法用 delete 去除其所佔 的記憶體空間, 而 iptr 卻可以 比方說 :
delete iarray; /* error */ delete iptr; /* OK */ iptr = new int[200]; iptr is now an integer array of 200 elements. Question: What are the values of the following sizeof operations sizeof(iarray) sizeof(iptr)