C++ Pointer(指針)

一、什麼是指針

int a;
int *p;

指針同樣是一種變數,和一般變數的差別是它用來保存記憶體位址,比如a的記憶體位址在0x1234,p要保存a的位址存的就是0x1234

二、*和&符號介紹

&

如果將&接在一個變數前面,就會變成取得該變數的記憶體位址 ex:

int a = 10;
&a  // int *

而它的型別即是原本的加上一個*
原本是int,所以int的記憶體位址型別是int *
這也就是指針變數的型別有*的原因

所以用int *型別保存int變數的記憶體位址

int a = 10;
int *p = &a;  // p保存了a的記憶體位址,比如0x1234
cout << p;  // 0x1234

而當&接在型別之後,int &num,作用是Reference(參考),在這裡不講述

*

如果*接在一個指針變數前面,就會變成取得該指針保存的地址的值 ex:

int a = 10;
int *p = &a;  // p = 0x1234
cout << *p;  // 10

當a的記憶體位址是0x1234
p保存的就是0x1234
而*p的作用是取得0x1234這個位址的值 10

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

三、多重指針

int a = 10;
int *p = &a;
int **pp = &p;

&變數 的型別就是變數的型別加上*
int → int *
int * → int **
多層指針同樣是保存少一層指針的記憶體位址
比如int **用來保存int *的記憶體位址

只要是變數宣告的寫法(前面接著型別)
如int *p,int &num (Reference)
都會被當成*或&跟型別int在一起的
(int *)p 即使*和p連在一起,同樣是int * 如括號所示

四、陣列

[12, 24, 36, 48]

int arr[] = {12, 24, 36, 48};

首先陣列是連續的記憶體空間保存的,int大小為4byte
如果arr[0]位於0x1234
arr[1]則是0x1234+4(int大小)=0x1238
後續的同理
也就是可以透過開頭arr[0] 0x1234+4×N找到第N個索引值的記憶體位址

int arr[] = {12, 24, 36, 48};
int *p = arr;  // 隱含轉換成&arr[0]
// int *p = &arr[0];
// 雖然arr的記憶體位址&arr即是首元素的位址,不過可能因為型別問題產生錯誤
// int *p = &arr;  有可能報錯
cout << *(p+2); // 36
cout << arr[2]; // 36
cout << p[2];  // 36  如同第一個

指針的加法會加上型別大小
比如int * 加1實際上會是地址+4
int 4byte,所以0x1234~0x1237都在存放12這個值,0x1238~0x123B才是第二個元素28

五、建立物件

一般建立物件在C++使用class/struct的名稱加上()

class Test{}
...
Test t = Test();

new關鍵詞的作用是分配一塊對應的記憶體空間並返回開頭位址
用來存放xxx型別的記憶體位址是xxx *

class Test{}
...
Test *test = new Test();

上述為建立一塊Test記憶體空間,比如0x1234
或者說建立一個Test的物件並返回記憶體位址

可以用new的方式建立一個array並返回其開頭位址

int *arr = new int[10];
arr[0] = 1;

也可以new int()

int *num = new int(10);

六、為什麼要用指針

指針保存的是一個記憶體位址
而一個記憶體位址在64位元固定是8byte
也就是一個物件無論多大,使用記憶體位址來操作都是8byte的大小