接下來要講的是指標(pointer),其實之前在講陣列的時候,就已經有出現過 pointer 的應用,現在我們要來真的說說什麼是 pointer!
Pointer 是一種可以儲存 memory address 的變數,可以指向任何一種型態,不論 int、float。
其宣告方式為:
type pointed* pointer name;
常常與pointer搭配的還有&
,我們稱&
為 address-of operator,可以用這個符號來取得指標指向的變數之地址。
其使用方式為:
pointer name = &variable name;
要注意的是,當賦予 pointer 一個 address 的時候,那個變數與指標的 type 要相同。
例如:
int a = 5;
int* aPtr = &a;
其中的aPtr
就是指向a
,存著a
的 address,而a
、aPtr
的型態皆為 int。
double b = 10.5;
double* bPtr = &b;
其中的bPtr
就是指向b
,存著b
的 address,而b
、bPtr
的型態皆為 double。
兩個 pointer不能相加,但可相減。例如:
double a[3] = {10.5, 10.6, 10.7};
double* b = &a[0];
double* c = &a[2];
cout << c - b; // 2
這個2
代表b
、c
差兩格。
所以到目前為止,整理一下:&
:address-of operator ->回傳 variable’s address*
:dereference operator -> 回傳 pointed variable
舉例來說:
int a = 5;
a:5
&a:回傳`a`的地址
int* aPtr = &a;
aPtr:存`a`的地址
&aPtr:回傳’aPtr’的地址
*aPtr:回傳`a`
其實有點像是邏輯問題,搞懂需要一點時間....
如果搞懂的話,這邊再補充一下:
int a = 10;
int* ptr = &a;
*ptr = 5;
若程式碼長這樣,a
的值就會變成 5。
宣告的時候,我們可以將一個指標初始化為nullptr
,也就是他並沒有指向任何東西:
int* ptr = nullptr;
此時若cout << *ptr
,會發生 run-time error到情況!
接下來要說説傳值的兩種方法:
Call by reference
什麼是“reference”呢?其實就是一個變數的別名!
例如我們寫
int &d = c;
就是宣告 d 是 c 的 reference,也就是說,d = 20 的話,c 就是 20。
但是不能寫
int &d = 10;
Call by pointers
其實就是 call by address,舉個例,我們寫一個叫swap
的函數,若將兩數值傳入,就能將其交換:
void swap(int *ptrA, int *ptrB) {
int temp = *ptrA ;
*ptrA = *ptrB;
*ptrB = temp;
}
int main() {
int a = 1;
int b = 0;
cout << a << "," << b << "\n"; // 1, 0
swap(&a, &b); // 傳入a, b的address進行交換
cout << a << "," << b << "\n"; // 0, 1
return 0;
}
輸出後,我們可以看到a
與b
值交換了,這是將a
和b
傳入的address進行交換,之後在main 裡面利用&
符號傳入 address。
最後,要介紹前面就提過的動態陣列(dynamic memory allocation)。
int* a = new int[5];
我們都知道這是宣告一長度為5的動態陣列,不過我到現在才知道,原來其中的new
是代表:配一塊空間並回傳其 address。
Memory leak
在動態陣列中,且還在 run time 時,系統不會自己釋放動態陣列的記憶體(若是固定的陣列就會),因為這個空間是沒有名字的。
因此,為了避免 code 佔太多記憶體空間,下面要寫 delete statement,來手動釋放記憶體空間:
int* a = new int[5];
// statements
delete [] a;
二維動態陣列
若我們要宣告一個 n X m 的二維陣列,裡面各項都是 0:
int** array = new int*[n];
for (int i = 0; i < n; i++) {
array[i] = new int[m];
for (int j = 0; j < m; j++) {
array[i][j] = 0;
}
}
// statements
delete [] array;
最後也要記得加上 delete statement。
Pointer 的筆記就到此為止,對於 pointer 的概念我還是有點似懂非懂,希望再多練習幾題題目後,我能更熟悉!