1. 程式人生 > >按值傳遞引用型別&按引用傳遞引用型別

按值傳遞引用型別&按引用傳遞引用型別

值型別和引用型別

與引用型別相對的是值型別。

值型別

當把一個值型別賦給另外一個時,就是對欄位成員逐一進行復制,此時在棧上新建了值型別的兩個副本,每一個都可以被獨立操作。

引用型別

和棧中的值型別相比,當對引用型別應用賦值操作符時,我們就是在記憶體中重定向引用變數的指向。
其中,所有類例項都是引用型別。

按值傳遞引用型別

回顧一下形參和實參

這裡寫圖片描述
在一般傳值呼叫的機制中只能把實參傳送給形參,而不能把形參的值反向地傳送給實參。因此在函式呼叫過程中,形參值發生改變,而實參中的值不會變化。而在引用呼叫的機制當中是將實參引用的地址傳遞給了形參,所以任何發生在形參上的改變實際上也發生在實參變數上。
參考:

https://baike.baidu.com/item/%E5%BD%A2%E5%8F%82/7677757?fr=aladdin

按值傳遞引用型別例項

假設有一個Person類,一個方法:void SendAPersonByValue(Person p)

void SendAPersonByValue(Person p){
  //改變"p"的年齡
  p.personAge = 99;
  //呼叫者能看到這個重新賦值嗎?
  p = new Person("Nikki",99);
}

假設在Main()函式中,呼叫函式的程式碼如下:

Person fred = new Person("Fred"
,12); SendAPersonByValue(fred);

結果顯示,fred傳進函式中後,他的personAge被改成了99(p.personAge = 99)
但是函式中的 p = new Person(“Nikki”,99);並未起作用。

結果解釋

值傳遞方式下,形參是複製於實參的。
如果傳入的是值型別,那很簡單,就和預期一樣,形參和實參完全沒有關係。
而如果傳入的是引用型別,那麼會複製指向呼叫者物件的引用。
即p是一個引用變數,複製於傳進來的fred變數,都指向了記憶體中的同一處,通過p改變該記憶體的值,fred引用也會看到變化,但是如果通過p 新建一份的記憶體區,那就和fred指向的記憶體區沒有什麼關係了。

按引用傳遞引用型別

如果把之前的函式改寫成按引用傳遞引用型別,其形式如下:(C#語言)

void SendAPersonByValue(ref Person p){
  //改變"p"的年齡
  p.personAge = 99;
  //fred引用變數也會受到影響,p和fred指向了堆上的一個新物件
  p = new Person("Nikki",99);
}

此時,Main()函式中的fred引用變數也會受到影響

參考書籍:《精通C#(第六版)Andrew Troelsen》章節4.5