老生常談C 中實參形參的傳遞問題

2022-10-04 01:21:13 字數 3036 閱讀 3131

函式中引數的傳遞

這裡說的傳遞當然是指 實參是如何傳遞給形參的啦

還挺複雜的~~~~~~~~⊙﹏⊙b汗,這裡講述了4種引數傳遞的情況和注意事項:

1.非引用形參

這是最普通,也是最簡單的形參傳遞了。

引數傳遞,即是使用實參副本(注意啊,是副本,不是實參本身)來初始化形參;

因此,在函式體內對形參的修改不會影響實參的值。

如果形參是指標型別的,那麼函式體內是否可以修改指標所指向的物件的值呢?

如果您產生這樣的疑問,表示您很有想法~~~

答案是~~~需要分情況討論。

如果函式的形參是非const型別的指標,則函式可以通過指標實現賦值,修改指標所指向物件的值。

所以,如果需要保護指標指向的值,則形參需定義為指向const物件的指標(注意了,這裡的指標依然是非const型的,只是其指向的物件是const型的):

void use_ptr(const int *p)

const形參

如果函式使用的是非引用非const形參,則既可以給該它傳遞const實參,也可傳遞非const實參。

如果函式使用的是非引用const形參,也是既可以給該它傳遞const實參,也可傳遞非const實參。那麼這兩者的差別是什麼呢?對於後者,函式連實參的區域性副本都不可以改變了。下面是第二種情況的乙個例子: void fcn(const int i) {}

複製實參的侷限性:複製實參不是在所有的情況下都適合,不是一複製實參的情況如下:

1.當需要在函式中修改實參的值時

2.當需要以大型物件作為實參傳遞時。對實際的應用而言,複製物件所付出的時間和www.cppcns.com儲存空間代價往往過大

3.當沒有辦法實現物件的複製時

對於上述幾種情況,有效的解決辦法是將形參定義為引用或指標型別。

(終於說完這個最簡單的傳遞方式了,╮(╯▽╰)╭)

2.引用形參

引用形參的用法:

1.讓函式修改實參的值

2.向主調函式返回額外的結果(本來return就可以返回乙個值給主調函式,而且引用引數可以改變實參的值,所以相當於返回了額外的結果)

3.利用const引用避免複製(當向函式傳遞大型物件時,需要使用引用來提高效率,如果使用引用形參的唯一目的是避免複製實參,則應將形參定義為const引用)

這是乙個不適宜複製實參的例子,該函式希望交換兩個實參的值

void swap (int v1,int v2)

這個例子期望改變實參本身的值,但是swap無法影響實參本身,執行swap時,指示交換了其實參的區域性副本,對實參根本沒有改變。解決的方法是:將形參定義為引用型別。

void swap (int &v1,int &v2)

當呼叫swap(i,j)時,i和j的值才真正實現了交換。

更靈活的指向const的引用

應該將不需要修改的引用形參定義為const引用。普通的非const引用形參在使用時不大靈活。非const引用形參既不能用const物件初始化,也不能用字面值或者產生右值的表示式實參初始化。(如果函式的形參是非const引用形參,表示在函式體內可能會修改該形參值,即會修改實參的值,因此不可以用const物件來做實參傳遞給這樣的函式,所以不靈活。)

傳遞指向指標的引用

如果想編寫乙個與前面交換兩個整數的swap類似的函式,實現兩個指標的交換。已知需用*定義指標,用&定義引用,問題在於,如何將這兩個操作符結合起來一獲得指向指標的引用。

//交換兩個指向整形的指標的值

void ptrswap(int *&v1,int *&v2)

形參int *&v1的定義,應該從右至左的理解:v1是乙個引用,與指向int型物件的指標相關聯。也就是說,v1只是傳遞ptrswap函式的任意指標的別名。

3.vector和其他容器型別的形參

由於複製vector會使得效率降低,多以如果形參是vector的話,我們常常將該形參宣告為引用,避免複製。另一種方法在c++中更為常用,就是通過傳遞指向容器中需要處理的元素的迭代器來傳遞容器。

4.陣列形參

由於陣列是不可以複製的,所以不可以定義使用陣列型別形參的函式。如果函式需要使用陣列作為形參,那麼就要通過操縱指向陣列中元素的指標來處理陣列。

以下定義都是正確的:

void printvalues(int*){}

void printvalues(int){}

void printvalues(int[10]){}

注意了,雖然不能直接傳遞陣列,但是函式的形參可以寫成陣列的形式。上面三種定義是等價的,形參類洗個都是int*。

通常,將陣列形參直接定義為指標要比使用陣列語法定義更好。這樣就明確地表示,函式操縱的是指向陣列元素的指標,而不是陣列本身。由於忽略了陣列長度,形參定義中如果包含了陣列長度則特別容易引起誤解。

對於非引用型形參來說,編譯器檢查陣列形參關聯的實參時,它只會檢查實參是不是指標、指標的形參和陣列元素的型別是否匹配,而不會檢查陣列的長度,所以即使實參陣列的長度與形參不匹配時,編譯也可以通過,但是在呼叫時會出錯。

但是對於引用型形參來說,編譯器還會檢查是西安陣列的大小與形參的大小是否匹配,所以如果實參陣列的長度與形參不匹配,編譯時就會報錯。

如何確保函式的操作不超出陣列實參的邊界?

方法有三:

1.在陣列本身放置乙個標記來檢測陣列的結束。c風格字串就是採用這個方法的乙個例子,它是乙個字元陣列,並且以空字元null作為結束的標記。處理c風格字串的程式就是使用這個標記停止陣列元素的處理。

2.使用標準庫規範,傳遞指向陣列第乙個和最後乙個元素的下乙個位置的指標。void printvalues(const int *beg, const int *end){},如果定義int j[2]=,在呼叫該函式時,printvaluvjbkqvnges(j,j+2).

3.顯式傳遞表示陣列大小的形參。void printvalues(const int ia, size_t size){}

5.可變形參

c++中的省略符形參是為了編譯使用了varargs的c語言程式。

void foo(parm_list,...);

void foo(...);

本文標題: 老生常談c++中實參形參的傳遞問題

本文位址: /ruanjian/c/182106.html

老生常談c 中的靜態成員

有時候需要類的一些成員與類本身相關聯,而不是與類的每個物件相關聯。比如類的所有物件都要共享的變數,這個時候我們就要用到類的靜態成員。宣告靜態成員的方法是使用static關鍵字。static成員可以是public也可以是private的。例如,定義乙個類表示銀行的賬戶記錄 class account ...

老生常談javascript的5中繼承

js裡常用的如下兩種繼承方式 原型鏈繼承 物件間的繼承 類式繼承 建構函式間的繼承 在物件導向的語言中,我們使用類來建立乙個自定義物件。然而js中所有事物都是物件,那麼用什麼辦法來建立自定義物件呢?這就需要用到js的原型 我們可以簡單的把prototype看做是乙個模版,新建立的自定義物件都是這個模...

實參到形參的傳遞

函式呼叫時,實參傳遞到形參時的轉換問題?要點 void swap int x,int y int main void swap int px,int py int main 程式中,雖然pa始終指向a,pb始終指向b,但是a與b的值已發生了交換。int plus int x,int y int ma...