C++ 入門指南 V2.00 - 單元 4 - 指標與參考




指標 (pointer) 儲存變數 (variable) 的記憶體位址 (address) ,參考 (reference) 則是變數的別名 (alias)



C++ 中,除了基本內建型態與指標外,其他的變數大都可看作是物件,指標是承接自 C 語言儲存記憶體位址的概念,如果指標運用得宜就可以寫出相當有效率的程式。

由於指標是儲存記憶體位址的資料型態,因此都可用指標指向基本內建型態或物件。宣告 (declare) 指標變數使用星號運算子,舉例如下


001 #include <iostream>
002
003 using namespace std;
004
005 int main(void) {
006    // 設定 n 為整數 11
007    int n = 11;
008    cout << n << endl;
009
010    // 設定 nPtr 為指向 n 的指標
011    int *np = &n; // & 是取址運算子
012    cout << np << endl;
013
014    // 設定 t 取得從 np 位址指向的值
015    int t = *np; // * 是反參考運算子
016    cout << t << endl;
017
018    return 0;
019 }
020
021 /* 檔名: pointer_demo.cpp
022    作者: Kaiching Chang
023    時間: 2014-5 */

這個例子中,我們先宣告整數變數 n ,並且設定為 11


006 // 設定 n 為整數 11
007 int n = 11;
008 cout << n << endl;

然後用 np 取得 n 的記憶體位址。須留意 np 的前面(等號左邊)加星號表示是指標,而這個星號運算子 * 用為宣告指標,指標的型態 (type) 必須與取得記憶體位置變數的型態相符,等號右邊則是利用取址運算子 (address-of operator) & 取得變數 n 的記憶體位置


010 // 設定 nPtr 為指向 n 的指標
011 int *np = &n; // & 是取址運算子
012 cout << np << endl;

下面則是利用反參考運算子 (dereference operator) ,同樣是星號 * ,但是出現在等號的右邊,由 t 取得 np 所儲存記憶體位置變數的值,這裡 np 儲存的是 n 的記憶體位址, n 的值為整數 11


014 // 設定 t 取得從 nPtr 位址指向的值
015 int t = *np; // * 是反參考運算子
016 cout << t << endl;

會不會有點霧沙沙的呢?來編譯執行看看囉



指標就是儲存某個物件的記憶體位址,取址運算子用來取得變數或物件的記憶體位址,至於反參考運算子可從指標取得指向物件的值。


腦袋有沒有比較清楚了呢?大型程式常常上上下下、左左右右都是 *& ,我們在這裡先把這個容易搞混的地方用簡單的例子說明,另舉一個例子如下,連帶介紹參考 (reference) 與 new 關鍵字 (keyword)


001 #include <iostream>
002 #include <string>
003
004 using namespace std;
005
006 int main(void) {
007    // a 為字串變數
008    string a = "There is no spoon.";
009    cout << a << endl;
010
011    // b 為對 a 的指標
012    string *b = &a;
013    cout << b << endl;
014
015    // c 為對 a 的參考
016    string &c = a;
017    cout << c << endl;
018
019    // d 為另一個指標
020    string *d = new string("There is no spoon.");
021    cout << d << endl;
022
023    return 0;
024 }
025
026 /* 檔名: pointer_demo2.cpp
027    作者: Kaiching Chang
028    時間: 2014-5 */

宣告參考變數用到與取址運算子相同的 & ,但這出現在等號的左邊


015 // c 為對 a 的參考
016 string &c = a;
017 cout << c << endl;

簡單來說,參考只是個別名,這個例子 ca 都是相同的字串 (string) 物件 (object) 。


下面用 new 建立新的字串物件, new 建立的物件就必須放在指標之中


019 // d 為另一個指標
020 string *d = new string("There is no spoon.");
021 cout << d << endl;

new 與指標為建立物件的另外一種方式,此例編譯執行結果如下



總和以上來說, & 出現在等號左邊時用為宣告參考,出現在等號右邊是當作取址運算子,而 * 出現在等號左邊時用為宣告指標,出現在等號右邊則是反參考運算子。


有清楚了嗎?不過 &* 還有其他用法唷!碰到再介紹好了,接下來我們先來談談變數命名規則。


中英文術語對照


指標 pointer
變數 variable
位址 address
參考 reference
別名 alias
宣告 declare
型態 type
取址運算子 address-of operator
反參考運算子 dereference operator
參考 reference
關鍵字 keyword
字串 string
物件 object

重點整理


  1. 指標用來儲存記憶體位址,宣告指標變數使用 * 運算子,可用取址運算子 & 取得記憶體位址。
  2. 參考是變數的別名,宣告參考使用 & 符號。
  3. 若用指標指向物件,新建物件須用 new 關鍵字及建構函數初始化物件,字串則可用字面常數的形式直接指派。

問題與討論


  1. 為什麼指標運用得宜,可以寫出相當有效率的程式?
  2. 反參考運算子用於指標所指向變數的值,是否也可以用於設定指標所指向變數的值呢?
  3. 參考的用途為何?指標跟參考可以互相替代嗎?

練習


  1. 寫一個程式 exercise0401.cpp ,先宣告一個 int 型態的變數 a ,並將 a 的值設定為 1 ,然後用指標 pa 取得 a 的記憶體位址。
  2. 承上題,另寫一個程式 exercise0402.cpp,除了加入 exercise0401.cpp 的內容外,繼續加入一行 *pa = 2; ,觀察 a 的值是否有改變。
  3. 承上題,另寫一個程式 exercise0403.cpp,除了加入 exercise0402.cpp 的內容外,繼續加入一個參考變數 ra ,以 ra 當作 a 的別名。
  4. 承上題,另寫一個程式 exercise0404.cpp,除了加入 exercise0403.cpp 的內容外,並將 ra 更改為 3 ,觀察 a 的值是否有改變。

the end

4 則留言:

winage 提到...

練習題2 繼續加入一行 *pa = 2
可是結果都一直指pa之前宣告過了
該怎麼寫呢 謝謝

Unknown 提到...

錯別字:new 與指標為建立物件的"例"外一種方式,
"另"外一種方式

Unknown 提到...

錯別字:宣告參考變數用到與取"值"運算子相同的 &
與取"址"運算子相同的 &

Kaiching Chang 提到...

已修改,感謝指正 ^_^