前言
前幾天問 GPT 問的,單獨拎出來當作筆記的一個補充吧。
指標的基本概念
指標(Pointer) 是一個變數,它儲存的是另一個變數的記憶體地址。在 C++ 中,定義一個指標變數時使用 *
符號,這個符號並不是表示解引用,而是表示這個變數是一個指標變數,指向某種型別的資料。
例子
int a = 5;
int* p = &a; // p 是一個指向 a 的指標,&a 獲取 a 的地址
在上面的例子中,&a
表示獲取 a
的記憶體地址,而 int* p
表示定義一個指向 int
型別的指標變數 p
。*p
表示解引用,訪問指標 p
指向的記憶體位置中的資料。
解引用的概念
解引用(Dereferencing) 是指透過指標訪問它指向的記憶體地址中的內容。當你使用 *p
時,你是在訪問指標 p
儲存的地址所指向的資料,而不是地址本身。
例子
int a = 5;
int* p = &a; // p 儲存 a 的地址
cout << *p; // 解引用 p,輸出 5,因為 p 指向 a
重要概念: *p
代表解引用,訪問的是指標 p
所指向記憶體位置中的資料,而不是 p
本身。也就是說,*p
是訪問 a
的值(即 5
),而 p
只是儲存了 a
的地址。
引用與指標的區別
引用(Reference) 只是某個物件的別名,透過引用,你直接操作原始物件的資料。引用變數不儲存記憶體地址,只是對已有物件的別名,不能為 null
或空指標。
例子
int a = 5;
int& ref = a; // ref 是 a 的引用
ref = 10; // 修改 ref 的值,a 變為 10
cout << a; // 輸出 10,a 被修改了
在這個例子中,ref
直接代表 a
,修改 ref
就等於修改 a
。沒有像指標那樣透過解引用去訪問,引用的操作更直接、簡潔。
常見誤解:*p = &x
和 *p
的使用
我前面提到了一個問題,就是:為什麼 *p = &x
不成立,而 *p
作為解引用操作並沒有做到“放地址”。這實際是理解上的一個小誤區。
關鍵點
定義指標時,*p
是用來宣告指標的型別,它告訴編譯器 p
是一個指向某型別(如 int
)的指標。而 &x
是取地址操作,表示你要拿到 x
變數的記憶體地址。
*p = &x
其實是錯誤的,因為 *p
不是儲存地址的地方,它應該儲存的是值,而不是一個地址。正確的做法是:
int x = 10;
int* p = &x; // p 儲存的是 x 的地址
*p = 20; // 解引用 p,把 x 的值改成 20
cout << x; // 輸出 20,x 的值被修改了
正確理解: 當你用 *p
進行解引用時,它實際上是指向 p
所指向的記憶體位置的內容。所以 *p
用於訪問指標指向的物件的值,而不是用來放地址的。
引用與指標的比較
特性 | 引用(Reference) | 指標(Pointer) |
---|---|---|
定義時初始化 | 必須在定義時初始化,一旦初始化後無法改變。 | 可以初始化為 nullptr ,並且可以隨時改變指向的物件。 |
儲存內容 | 儲存物件的別名,沒有獨立的記憶體地址。 | 儲存的是一個記憶體地址,指向某個物件。 |
是否為空 | 不可以為空,引用必須繫結到一個物件。 | 可以為空(nullptr ),也可以指向不同的物件。 |
訪問方式 | 直接使用引用變數名即可訪問原始物件。 | 使用 * 運算子解引用來訪問指標所指向的內容。 |
是否可以改變 | 一旦繫結,引用無法指向其他物件。 | 可以改變指標指向的物件,甚至指向 nullptr 。 |
適用場景 | 適用於不需要重新繫結的物件,通常用於修改物件的值。 | 適用於需要靈活指向不同物件、動態記憶體分配和處理連結串列等。 |
例子:引用和指標的操作對比
#include <iostream>
using namespace std;
void byReference(int& ref) {
ref = 10; // 透過引用修改原始值
}
void byPointer(int* p) {
*p = 20; // 透過指標解引用修改原始值
}
int main() {
int a = 5;
int b = 15;
byReference(a); // a 透過引用傳遞給函式,a 變為 10
byPointer(&b); // b 透過指標傳遞給函式,b 變為 20
cout << "a: " << a << endl; // 輸出 a: 10
cout << "b: " << b << endl; // 輸出 b: 20
return 0;
}
引用:直接作為別名運算元據,語法簡單且無需解引用。指標:儲存的是地址,需要透過解引用來訪問指向的資料,使用時更靈活。
常見的使用場景
引用 常用於函式引數傳遞(避免傳值開銷),或者需要直接修改原始物件的場景。指標 常用於動態記憶體分配(new
和 delete
)、資料結構(連結串列、樹)、以及需要操作多個物件或空指標的場景。
總結
指標 是一個變數,它儲存了某個物件的記憶體地址,並且透過 *
來解引用,訪問或修改指向的物件的內容。引用 是某個物件的別名,它直接代表物件本身,不需要解引用操作,操作簡潔。在 定義指標時,*p
只是用來告訴編譯器 p
是一個指標型別變數,而 解引用 是透過 *p
訪問指標指向的內容。