Reference 變數
-
Reference 變數
- 宣告/定義 reference variable 絕對沒有向系統要新的盒子來用, 只是給先前就已經要來的盒子取另外一個名字而已 (alias).
- & 永遠不會出現在 C 語言變數宣告的形態部分. (可以出現在起始值)
- 在 C++ 中, & 出現在程式的運算式中, 要唸作 "... 的位址"; 出現在變數宣告的形態部分, 要唸作 "... 是一個 reference variable".
-
再強調一次: 不要跟指標混淆:
int x; int x; int *p = &x; int &y = x;
Q: 向系統要了幾個盒子? 各裝什麼? 請圖示. - 出現在變數宣告的形態部分當中的 & 不影響變數的形態.
-
Call by reference
- 記得 C 語言副程式呼叫時, 每寫一個形式參數其實都是在宣告/定義一個自動變數嗎? 函數的參數列其實也是變數宣告/定義的地方. 如果這裡放的是 reference variable , 可以想像它的意思就是: 並未向系統要新的盒子, 形式參數其實只是實際參數的別名.
-
結論: C++ 除了 call-by-value 外, 還有 call-by-reference. 例:
void swap(int & a, int & b) { int c; c = a; a = b; b = c; }
假設有int x, y;
, 則呼叫swap(x,y)
會將 x 與 y 的內容對調過來. 請圖示. - Q:
printf("%d", x)
和printf("%d", x+3)
都正確; 那麼swap(x,y)
和swap(x+3, y+3)
呢? 結論: "傳給 reference variable 的實際參數必定是 ..." - Q: 為什麼陣列參數不可以也不需要以參考方式傳遞? 作業: 寫一個函數 itoa, 接受以下參數: 字串 result, 整數 n, 整數 r (內定值 16). 它將 n 以 r-進位印至 result 內. 從 skeleton.c 開始修改. 可否不要用臨時字串?
- 傳遞比較大的記錄當做副程式參數時, C 語言中習慣上以指標傳遞, 如果副程式不會修改到這個指標所指到的變數, 則宣告成指到常數的指標. 同樣的情況, 換作 C++, 則習慣以 reference variable 傳遞, 而如果副程式不會修改到這個 reference variable 所代表的本尊, 則宣告成參考到常數的 reference variable .
- Q: 將不是 const, 不是 reference 的參數傳給以 const & 為參數的副程式, 會不會有問題?
- 除非函數名稱可以明顯提示傳進去的參數會被修改, 否則避免傳遞非常數的參考.
-
傳回 reference
- C 語言中, 不僅參數傳遞時發生拷貝的動作, 傳回參數時亦同. 例:
設有
int min(int x, int y) { return x < y ? x : y; }
則min(a, b) = 3
將導致 compile-time error. - 在 C++ 中, 上述函數若改宣告為:
int & min(int const & x, int const & y);
(定義完全不變), 則可將傳回值作為 l-value 使用. - 結論: 有三種變數可能可以當做 reference 傳回: 以 reference 傳入的參數, 用 new 要來的變數, 靜態變數 (包含全域變數與局部的 static 變數). 其實道理和傳回指標時, "不可以指向已經不存在的東西" 一樣.
- 作業:
(x=5) = 3;
若出現在 .c 的程式當中, 編譯結果如何? 若出現在 .cc 的程式當中, 編譯結果如何? -
最常使用傳回 reference 的場合:
ostream & operator << (ostream & os, complex c);
請與 strcpy 和 strcat 等傳回指標的函數做比較: 傳回值其實都是主程式傳進去的東西, 這麼做只是為了方便主程式直接把傳回值繼續拿來傳給下一個函數, 不必分成好幾次呼叫. - 作業: 將 stack.c 和 complex.c 改寫為 C++ 程式. 簡化所有函數的界面, 刪除所有的參數及傳回值中的指標.
- C 語言中, 不僅參數傳遞時發生拷貝的動作, 傳回參數時亦同. 例:
設有
- 本頁最新版網址: https://frdm.cyut.edu.tw/~ckhung/b/cxx/reference.php; 您所看到的版本: February 14 2012 10:32:25.
- 作者: 朝陽科技大學 資訊管理系 洪朝貴
- 寶貝你我的地球, 請 減少列印, 多用背面, 丟棄時做垃圾分類。
- 本文件以 Creative Commons Attribution-ShareAlike License 或以 Free Document License 方式公開授權大眾自由複製/修改/散佈。