close

C++語言相關探討,細究指標(pointer)與參照(reference)


  1. 指標(Pointer)與參照(Reference)  
    在C++語言中,雖然指標與參照在使用上極為類似,但是實際上有許多地方式都是不同的。我將這些不同做成以下列表出來:

      指標(Pointer)    
    (type *p)
    參照(Reference)
    (type &p)
    記憶體配置 配置指標記憶體(4Byte) 不配置記憶體,本身為別名(Alias)
    初始值給定 可以後來指定(不建議,但是允許這樣給值) 必須在變數成立的時候,直接給定初始值
    內容值(p) 代表一個記憶體位置,指向給定的目標值 直接代表目標值
    設定位置
    (目標值Q)
    p=&Q p=Q
    (在此為將Q另外設定一個名字p)
    給值
    (目標值Q)
    *p=Q
    (將Q的值給*p)
    p=Q
    (在此為將Q另外設定一個名字p)


    根據以上的表格,順道提到一般課本常提到的Call by address與 Call by reference的參照方式,撰寫如下:

     

    Call by Address
    (use Pointer)

    Call by Reference
    (use Reference)

    #include <iostream.h>
    void fun1(int * p, int * q)
    {
      *p=*p+*q;
    }

    void main()

      int i=3,j=4,k;
      fun1(&i,&j);
      cout <<i;
    }

    #include <iostream.h>
    void fun1(int & p, int & q)
    {
      p=p+q;
    }

    void main()

      int i=3,j=4,k;
      fun1(i,j);
      cout <<i;
    }

    透過這個列表,可以清楚的兩者的差異,所以在之前文章所提到的錯誤為:

     int x=10;
     int *v;
     *v=x;
    ;

    在此錯誤為,由於我的指標 *v 並沒有初始化指標,所以v的值是一個系統給的亂數(或是之前變數留下來的資料),其實這樣去指定是相當危險的一件事情。所以要設定v去指定x的時候,應該使用  v=&x 去設定一個位置在v之中。之前會這樣想也因為我對於字串指標的設定有一點混淆 char *s="test ~~~ string~~~"; 像這樣的句子,雖然也是起使一個指標,但是由於電腦會先根據字串"test ~~~ string~~~"去分配一個位置給他,然後再把位置指定給s ,所以不需要再配置一次位置(記得這個問題在趨勢與友立似乎也一直被問到~~)

    但是這裡順道一提 : char *str1="test ~~~ string~~~"; 與 char str2[]="test ~~~ string~~~"; 若要顯示整段文字,勢必得使用 "cout<<"STRING:"<<str1<<endl;" / " cout<<"str2="<<&str2[0]<<endl;" / "cout<<"str2="<<str2<<endl;",因為cout <<*str1; 只會顯示出第一個字元,而 " cout <<sp[];" 則是語法錯誤cout<<str1;  則會顯示整個字串,這也是字串與指標的一種混和運用。太久沒寫的人(像我),這邊也會有種混淆的感覺@﹍﹍﹍@

  2. 同樣在『』的第30條之中,裡面有提到一個概念(Reference Counting ),主要是利用運算子多載(Operator Overloading)的概念,將 =  (Assign給值)這個運算子,更改其用途,來節省記憶體的使用。一般而言,若是有效的參照與節省記憶體 (Reference Counting )

    More Effective C++

    String a,b,c,d,e;
    a=b=c=d=e="Hello";

    在以上的程式之中,記憶體是會分配『五塊記憶體(大小為STRING)』,因為原來在String中的運算子『=』的定義是Assign by Copy的方式,也就是會同樣的分配一塊記憶體,然後複製其內容值到每一塊記憶體之中。所以若是針對 『=』加以更改其作用值,若是在參考的時候(也就是單純的String 互傳值)的話,應該是將記憶體節省下來,直接讓LHS(左手邊的變數)直接指向RHS(右手邊)的變數才對。並且還要可以計數所有有參照到該記憶體的變數個數(所以才叫Reference Counting),詳細說明,請看『More Effective C++』的P.183

Note:

char* s = "abcde"; 和
char s[] = "abcde";
有著根本上的不同,你把他們丟到某些字串函數會有不同的行為

需要分清楚char*, const char*, const char[], text literal四者之間的區別
為了避免誤用,盡量使用const char* s = "something..."代替char* s = "something..."
Effective C++ Item 21最後面的注解(我的是英文版,不知道中文版有沒有)

做個實驗就會發現
char* s1 = "abcde";
char* s2 = "abcde";
char s3[] = "abcde";
char s4[] = "abcde";

如果你去印出他們的指標值如
printf("%p\n", s1); //%p希望沒記錯
會發現s1和s2是一樣的,而s3和s4不同
而你再去宣告
char* skk = "abcde";
char* ppp = "abcde"; 記憶體位址仍然相同

在c語言中是沒有call by reference 與call by address的差異性這一回事的。應該是說call by pointer 與call by reference 的差異性,而這兩者皆屬於call by address。(候捷的書也是這麼說,請詳讀)


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Bluelove1968 的頭像
    Bluelove1968

    藍色情懷

    Bluelove1968 發表在 痞客邦 留言(0) 人氣()