釋出者:
2012年10月21日 (最後更新: 2012年10月22日)

指標和引用

評分: 3.1/5 (236 票)
*****
指標或引用(有人稱之為別名)。編譯器真的在意嗎?

讓我們做一個簡單的實驗,我相信這能幫助任何想理解指標和引用的人。

讓我們宣告兩種簡單的函式版本
但暫時我們只使用 int& 版本。

1
2
      //void some_function(int* i){cout << "\nvalue is " << *i << endl;};
      void some_function(int& i){cout << "\nvalue is " << i << endl;};


區別在於一個接受整數的引用,而另一個
接受指標。到目前為止一切都很簡單,現在讓我們呼叫函式使用
指標。

初始化變數。這只是為了讓我們之後需要重新轉換 fp
,我的意思是它除了在這裡的例子之外沒有其他意義。
所以現在 fp 是一個指向某個位元組的指標。它不知道自己指向
一個函數了。
1
2
      char* fp = reinterpret_cast<char*>(&some_function);
      int ii = 5;


第一次呼叫 some_function,重新轉換 fp
1
2
      
      reinterpret_cast<void(*)(int&)>(fp)(ii);

這將輸出 ii 中的值,即 5。

所以沒問題,一切都很簡單。

第二次呼叫 some_function
現在讓我們稍微改動一下來呼叫它
1
2
  
    reinterpret_cast<void(*)(int*)>(fp)(&ii);


這當然會輸出相同的 5,因為它呼叫
的是同一個函式。但請注意,我使用了 int* 來轉換指標
而不是 int&,而我們正在使用的函式宣告是
int& 版本。

在第一次呼叫中,我們使用了正確的型別進行轉換,而且我們不用
透過 &ii 來呼叫。在第二種情況下,因為我們使用了 int* 來轉換
,我們需要透過 &ii 來呼叫,將其轉換為一個 POINTER。

我認為這個簡單的例子表明,當編譯器看到一個引用,並且有人用不同的簽名呼叫它,比如
int*,因為它那時已經將 int& 改為了到處都是 int*,所以它並不太在意。

換句話說,就編譯器而言,它只看到
 
void some_function(int* i){cout << "\nvalue is " << *i << endl;};

即使你寫成
 
void some_function(int& i){cout << "\nvalue is " << i << endl;};


而使用指標呼叫引用的呼叫將被更改為
使用指標的呼叫。

你可以嘗試註釋掉程式碼,用兩種方式呼叫函式,看看它們是如何工作的。

嗯,我希望這對某人有所幫助,或者至少讓他們覺得有趣。