2018年2月9日 星期五

參考 referance 重要性以及是為什麼而存在的

參考 referance 重要性以及是為什麼而存在的

參考與指針的詳細差別可以參考這一篇站內文有詳細介紹
https://charlottehong.blogspot.tw/2018/01/cc-point-refrence.html
今天要來說的是 referance 的重要性,也就是上偏內所提到的各種練習,下面是簡化過的版本。
void fun(int* i){ ++i; }
void fun(int& i){ ++i;}
他們之間有什麼差異,在練習裡我們的要求是修改一個輸入的變數,已經詳細的說明他們的差異,但是這些差異最終也只是可以彌補的差異並且可以被忍受。
彌補的定義是可以透過增加代碼來處理,比如說指針需要檢查有效性就是多打一行if檢查就完事了。
可以忍受的定義是,反正那行if就在最上方,一次性就ok搞定不會一直煩到我。下面要來說的是無法忍受的部分—-別名
之所以無法忍受的原因是變數名稱在程式內會出現很多次,你之後再打程式也可能會在用到,所以無法用別名就會一直被搞到。

別名的問題

來看這一段代碼
/********************************************************************************
Name : 
Date : 2018/02/09
By   : CharlotteHonG
Final: 2018/02/09
********************************************************************************/

#include <iostream>
using namespace std;

// Case1
void euq(int* dst, int* src) {
    if(!dst or !src) { printf("Erroe\n");return; }
    dst = src;
}
void euq_fix1(int** dst, int* src) {
    if(!dst or !src) { printf("Erroe\n");return; }
    *dst = src;
}

// Case2
struct Int2{
    int* is_a_long_names_parameter;
};
void euq2(Int2* dst, int* src) {
    if(!src) { printf("Erroe\n");return; }
    int* alia = dst->is_a_long_names_parameter;
    alia = src;
    }

#define k_alia(i) (i->is_a_long_names_parameter)    
void euq2_fix(Int2* dst, int* src) {
    if(!src) { printf("Erroe\n");return; }
    k_alia(dst) = src;
}
//================================================================
int main(int argc, char const *argv[]){
    int i=10, j=-1;
    int *p1=&i, *p2;

    cout << "*p1=" << *p1 << endl;
    p2=p1;
    cout << "*p2=" << *p2 << endl;

    int *p3 = &j;
    euq(p3, p1);
    cout << "*p3=" << *p3 << endl;

    int *p4 = &j;
    euq_fix1(&p4, p1);
    cout << "*p4=" << *p4 << endl;

    Int2 k;
    k.is_a_long_names_parameter = &j;
    euq2(&k, p1);
    cout << "*k=" << *k.is_a_long_names_parameter << endl;

    euq2_fix(&k, p1);
    cout << "*k=" << *k.is_a_long_names_parameter << endl;
    return 0;
}
//================================================================

// 執行結果
*p1=10
*p2=10
*p3=-1
*p4=10
*k=-1
*k=10
先看第一個案例 euq() 示範了直接等號卻沒有置換的問題,這個問題是出在參數的部分是 copy pass 也就是複製一份資料近來,當前有2個地址指向 i 一個是 main的一個是函式內的,你修改的是函式內的不甘外面的事情。
修復方法可以多一個 *,不過這可能會增加後面的人閱讀問題(到底是二維陣列還是?),就也是還可以忍受不是大問題。
問題出在第二個例子 euq2() 當出現一個超長別名的時候,或者是多重結構一堆 -> 這時候不用別名就真的很困擾了,然後直接取別名就會跟一開始一樣的錯誤。
在C語言裡面用 macro 可以處理這個問題,如上面的程式。但是最好的解決方式還是用參考直接引入參考進來就什麼事情也沒有。

沒有留言:

張貼留言