全面解析C 中引數傳遞

2022-02-05 05:03:48 字數 3342 閱讀 9089

對於一些初學者(包括工作幾年的人在內)來說,有時候對於方法之間的引數傳遞的問題感覺比較困惑的,因為之前在面試的過程也經常遇到引數傳遞的基礎面試題,這樣的面試題主要考察的開發人員基礎是否紮實,對於c#中值型別和引用型別有沒有深入的乙個理解——這個說的理解並不是簡單的對它們簡單乙個定義描述,而在於它們在記憶體中分布。所以本文章將帶領大家深入剖析下c#中引數傳遞的問題,並分享我自己的乙個理解,只有你深入理解了才能在不執行程式的情況就可以分析出引數傳遞的結果的。

對於c#中的引數傳遞,根據引數的型別可以分為四類:

然而在預設情況下,clr方法中引數的傳遞都是按值傳遞的。為了幫助大家全面理解引數的傳遞,下面就這四種情況一一進行分析。

class

program

//addnum就是形參,也就是被呼叫方法中的引數

private

static

void add(int

addnum)

}

對於值型別的按值傳遞,傳遞的是該值型別例項的乙個拷貝,也就是形參此時接受到的是實參的乙個副本,被呼叫方法操作是實參的乙個拷貝,所以此時並不影響原來呼叫方法中的引數值,為了證明這點,看看下面的**和執行結果就明白了:

class

program

//1. 值型別按值傳遞情況

private

static

void add(int

addnum)

執行結果為:

從結果中可以看出addnum呼叫方法之後它的值並沒有改變,add 方法的呼叫只是改變了addnum的副本addnum的值,所以addnum的值修改為2了。然而我們的分析到這裡並沒有結束,為了讓大家深入理解傳遞傳遞,我們有必要知道為什麼值型別引數的按值傳遞不會修改實參的值,相信下面這張圖可以解釋你所有的疑惑:

當傳遞的引數是引用型別的時候,傳遞和操作的是指向物件的引用(看到這裡,有些朋友會覺得此時不是傳遞引用嗎?怎麼還是按值傳遞了?對於這個疑惑,此時確實是按值傳遞,此時傳遞的物件的位址,傳遞位址本身也是傳遞這個位址的值,所以此時仍然是按值傳遞的),此時方法的操作就會改變原來的物件。對於這點可能看文字描述會比較難理解下面結合**和分析圖來幫助大家理解下:

class

program

//2. 引用型別按值傳遞情況

private

static

void

addref(refclass addnumref)

}class

refclass

執行結果為:

為什麼此時傳遞引用就會修改原來實參中的值呢?對於這點我們還是引數在記憶體中分布圖來解釋下:

對於string型別同樣是引用型別,然而對於string型別的按值傳遞時,此時引用型別的按值傳遞卻不會修改實參的值,可能很多朋友對於這點很困惑,下面具體看看下面的**:

class

program

//3. string引用型別的按值傳遞的特殊情況

private

static

void changestr(string

oldstr)

}

執行結果為:

對於為什麼原來的值沒有被改變主要是因為string的「不變性」,所以在被呼叫方法中執行 oldstr="new string"**時,此時並不會直接修改oldstr中的"old string"值為"new string",因為string型別是不變的,不可修改的,此時記憶體會重新分配一塊記憶體,然後把這塊記憶體中的值修改為 「new string」,然後把記憶體中位址賦值給oldstr變數,所以此時str仍然指向 "old string"字元,而oldstr卻改變了指向,它最後指向了 "new string"字串。所以執行結果才會像上面這樣,下面記憶體分布圖可以幫助你更形象地理解文字表述:

不管是值型別還是引用型別,我們都可以使用ref 或out關鍵字來實現引數的按引用傳遞,然而按引用進行傳遞的時候,需要注意下面兩點:

方法的定義和方法呼叫都必須同時顯式使用ref或out,否則會出現編譯錯誤

clr允許通過out 或ref引數來實現方法過載。如:

#region clr 允許out或ref引數來實現方法過載

private

static

void add(string

str)

//編譯器會認為下面的方法是另乙個方法,從而實現方法過載

private

static

void add(ref

string

str)

#endregion

class

program

#region 按引用傳遞

//1. 值型別的按引用傳遞情況

private

static

void changebyvalue(ref

intnumvalue)

//2. 引用型別的按引用傳遞情況

private

static

void changebyref(ref

string

numref)

#endregion

}

執行結果為:

到這裡引數的傳遞所有內容就介紹完了。總之,對於按值傳遞,不管是值型別還是引用型別的按值傳遞,都是傳遞實參的乙個拷貝,只是值型別時,此時傳遞的是實參例項的乙個拷貝(也就是值型別值的乙個拷貝),而引用型別時,此時傳遞的實參引用的副本。對於按引用傳遞,傳遞的都是引數位址,也就是例項的指標。

C 中陣列引數傳遞

include 傳遞陣列引數的幾種方式 void printvalues const int a 10 void printvalues2 int a 10 控制邊界 方法1 void printvalues4 int start,int end void printvalues5 const in...

C 中傳遞陣列引數

將陣列作為引數進行傳遞有兩種傳遞方法,一種是 function int a 另一種是 function int a 這兩種兩種方法在函式中對陣列引數的修改都會影響到實參本身的值!對於第一種,根據之前所學,形參是實參的乙份拷貝,是區域性變數。但是陣列是個例外,因為陣列的資料太多了,將其一一賦值既麻煩又...

C 中的引數傳遞

c 中的引數傳遞,根據引數的型別可以分為四類 在預設情況下,clr方法中引數的傳遞都是按值傳遞 對於引數又分為 形參 被呼叫方法中的引數,實參 呼叫方法的引數 class program addnum就是形參,也就是被呼叫方法中的引數 private static void add int addn...