函式的引數傳遞

ldw662523發表於2018-03-17

c語言中只有兩種引數傳遞,分別是傳值、傳指標
c++中包括傳值、傳指標、傳引用

按值傳遞的過程為:首先計算出實參表示式的值,接著給對應的形參變數在棧上分配一個儲存空間,該空間的大小等於該形參型別的,然後把以求出的實參表示式的值一一存入到形參變數分配的儲存空間中,成為形參變數的初值,供被呼叫函式執行時使用。這種傳遞是把實參表示式的值傳送給對應的形參變數,形參是實參的一個副本,故稱這種傳遞方式為“按值傳遞”。
使用這種方式,呼叫函式本省不對實參進行操作,也就是說,即使形參的值在函式中發生了變化,實參的值也完全不會受到影響,仍為呼叫前的值。
地址傳遞與按值傳遞的不同在於,它把實參的儲存地址傳送給對應的形參,從而使得形參指標和實參指標指向同一個地址。因此,被呼叫函式中對形參指標所指向的地址中內容的任何改變都會影響到實參
引用傳遞(pass-by-reference)過程中,被調函式的形式引數雖然也作為區域性變數在堆疊中開闢了記憶體空間,但是這時存放的是由主調函式放進來的實參變數的地址。被調函式對形參的任何操作都被處理成間接定址,即通過堆疊中存放的地址訪問主調函式中的實參變數。正因為如此,被調函式對形參做的任何操作都影響了主調函式中的實參變數。如果以引用為引數,則既可以使得對形參的任何操作都能改變相應的資料,又使得函式呼叫顯得方便、自然。引用傳引用傳遞方式是在函式定義時在形參前面加上引用運算子“&”。

  1. 從功能上。按值傳遞在傳遞的時候,實參被複制了一份,然後在函式體內使用,函式體內修改引數變數時修改的是實參的一份拷貝,而實參本身是沒有改變的,所以如果想在呼叫的函式中修改實參的值,使用值傳遞是不能達到目的的,這時只能使用引用或指標傳遞。
  2. 就引用傳遞和指標傳遞的效率上比,引用傳遞的效率始終不低於指標傳遞,所以從這種意義上講,在c++中進行引數傳遞時優先使用引用傳遞而不是指標。
  3. 從型別安全上講。值傳遞與引用傳遞在引數傳遞過程中都執行強型別檢查,而指標傳遞的型別檢查較弱,特別地,如果引數被宣告為 void ,那麼它基本上沒有型別檢查,只要是指標,編譯器就認為是合法的,所以這給bug的產生製造了機會,使程式的健壯性稍差,如果沒有必要,就使用值傳遞和引用傳遞,最好不用指標傳遞,更好地利用編譯器的型別檢查,使得我們有更少的出錯機會,以增加程式碼的健壯性。

    1. 從引數檢查上講。一個健壯的函式,總會對傳遞來的引數進行引數檢查,保證輸入資料的合法性,以防止對資料的破壞並且更好地控制程式按期望的方向執行,在這種情況下使用值傳遞比使用指標傳遞要安全得多,因為你不可能傳一個不存在的值給值引數或引用引數,而使用指標就可能,很可能傳來的是一個非法的地址(沒有初始化,指向已經delete掉的物件的指標等)。所以使用值傳遞和引用傳遞會使你的程式碼更健壯,具體是使用引用還是使用值傳遞,最簡單的一個原則就是看傳遞的是不是內建的資料型別,對內建的資料型別優先使用值傳遞,而對於自定義的資料型別,特別是傳遞較大的物件,那麼請使用引用傳遞。
  4. 從靈活性上。無疑,指標是最靈活的,因為指標除了可以像值傳遞和引用傳遞那樣傳遞一個特定型別的物件外,還可以傳遞空指標,不傳遞任何物件。指標的這種優點使它大有用武之地,比如標準庫裡的time( )函式,你可以傳遞一個指標給它,把時間值填到指定的地址,你也可以傳遞一個空指標而只要返回值。

相關文章