Reference 變數


  1. Reference 變數
    1. 宣告/定義 reference variable 絕對沒有向系統要新的盒子來用, 只是給先前就已經要來的盒子取另外一個名字而已 (alias).
    2. & 永遠不會出現在 C 語言變數宣告的形態部分. (可以出現在起始值)
    3. 在 C++ 中, & 出現在程式的運算式中, 要唸作 "... 的位址"; 出現在變數宣告的形態部分, 要唸作 "... 是一個 reference variable".
    4. 再強調一次: 不要跟指標混淆:
                      int x;                  int x;
                      int *p = &x;            int &y = x;
              
      

      Q: 向系統要了幾個盒子? 各裝什麼? 請圖示.
    5. 出現在變數宣告的形態部分當中的 & 不影響變數的形態.
  2. Call by reference
    1. 記得 C 語言副程式呼叫時, 每寫一個形式參數其實都是在宣告/定義一個自動變數嗎? 函數的參數列其實也是變數宣告/定義的地方. 如果這裡放的是 reference variable , 可以想像它的意思就是: 並未向系統要新的盒子, 形式參數其實只是實際參數的別名.
    2. 結論: 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 的內容對調過來. 請圖示.
    3. Q: printf("%d", x)printf("%d", x+3) 都正確; 那麼 swap(x,y)swap(x+3, y+3) 呢? 結論: "傳給 reference variable 的實際參數必定是 ..."
    4. Q: 為什麼陣列參數不可以也不需要以參考方式傳遞? 作業: 寫一個函數 itoa, 接受以下參數: 字串 result, 整數 n, 整數 r (內定值 16). 它將 n 以 r-進位印至 result 內. 從 skeleton.c 開始修改. 可否不要用臨時字串?
    5. 傳遞比較大的記錄當做副程式參數時, C 語言中習慣上以指標傳遞, 如果副程式不會修改到這個指標所指到的變數, 則宣告成指到常數的指標. 同樣的情況, 換作 C++, 則習慣以 reference variable 傳遞, 而如果副程式不會修改到這個 reference variable 所代表的本尊, 則宣告成參考到常數的 reference variable .
    6. Q: 將不是 const, 不是 reference 的參數傳給以 const & 為參數的副程式, 會不會有問題?
    7. 除非函數名稱可以明顯提示傳進去的參數會被修改, 否則避免傳遞非常數的參考.
  3. 傳回 reference
    1. C 語言中, 不僅參數傳遞時發生拷貝的動作, 傳回參數時亦同. 例: 設有 int min(int x, int y) { return x < y ? x : y; }min(a, b) = 3 將導致 compile-time error.
    2. 在 C++ 中, 上述函數若改宣告為: int & min(int const & x, int const & y); (定義完全不變), 則可將傳回值作為 l-value 使用.
    3. 結論: 有三種變數可能可以當做 reference 傳回: 以 reference 傳入的參數, 用 new 要來的變數, 靜態變數 (包含全域變數與局部的 static 變數). 其實道理和傳回指標時, "不可以指向已經不存在的東西" 一樣.
    4. 作業: (x=5) = 3; 若出現在 .c 的程式當中, 編譯結果如何? 若出現在 .cc 的程式當中, 編譯結果如何?
    5. 最常使用傳回 reference 的場合:
                  ostream & operator << (ostream & os, complex c);
              
      

      請與 strcpy 和 strcat 等傳回指標的函數做比較: 傳回值其實都是主程式傳進去的東西, 這麼做只是為了方便主程式直接把傳回值繼續拿來傳給下一個函數, 不必分成好幾次呼叫.
    6. 作業: 將 stack.ccomplex.c 改寫為 C++ 程式. 簡化所有函數的界面, 刪除所有的參數及傳回值中的指標.