c++ 参数传递
參數傳遞:
形參(parameter)和實參(argument):
int num (int a, int b); int num (int a, int b){return a+b; }//在函數的聲明或者定義里,由由0個或多個形參組成的列表。int main(){int n=1,m=1;cout<<num(n,m);//我們用調用運算符來執行函數,調用運算符形式是個圓括號,圓括號內是由逗號隔開的實參列表。我們用實參初始化函數的形參。 }形參的類型決定了形參實參交互的方式,如形參是引用類型,他將綁定到對應的實參上,引用形參是它對應實參的別名。否則,將實參的值拷貝后賦給形參。
當形參是引用類型,我們說,它對應的實參被引用傳遞(passed by reference)或者函數被傳引用調用(called by reference)。
當實參的值被拷貝給形參時,我們說,這樣的實參被值傳遞(passed by value)或者函數被傳值調用(called by value)。
傳值參數:
初始化一個非引用類型變量,初始值被拷貝給變量,對變量的改動不會影響初始值。
int n = 0; int i = n; i =1; cout << n;//輸出0,i的值改變,n的值不變。指針形參:指針的行為和其他非引用類型一樣,當執行指針拷貝操作,拷貝的是指針的值。拷貝之后,兩個指針是不同的指針。因為通過指針,我們可以間接訪問它所指對象,所以通過指針可以修改它所指對象的值。
void reset(int *ip){*ip = 0;//只改變了指針所指對象的值。ip = 0;//這里改變的只是ip的局部拷貝,實參并未改變 } int i = 1; reset(&i);//改變i的值而非i的地址 cout << "i = " << i <<endl;//輸出i=0。 —————————————————————————————————————— //實參類似于下面:(q) int i = 1; int *q = &i; //形參類似于下面:(p) int n = 0; int *p = &n; //實參調用形參類似與下面: p = q;//p指向了i *p = 2;//通過p改變了i,但是此時q并未改變。傳引用參數:
對于引用的操作,實際上是作用在引用所引的對象上。通過引用形參,允許函數改變一個或多個實參的值。
void reset (int &i){//形參i僅僅是實參j的又一個名字,在reset內部對i的使用即是對實參j的使用。i = 0;//改變了i所引對象的值。 } int j=1; reset(j);//j采用傳引用方式,因此他的值被改變。 cout<<j<<endl;//輸出j=0。傳引用參數:當形參是頂層const時,傳給他常量對象或者非常量對象都是可以的。
const int ci = 1; int i = ci;//正確,當拷貝ci時,忽略了它的頂層const。 int *const p = &i;//const是頂層的,不能給p賦值。 *p = 0;//正確,通過p改變對象內容是允許的。//在c++中,允許定義若干具有相同名字的函數,不過前提是不同函數的形參列表應該具有明顯區別。 void fcn(const int i){}//調用fcn函數時,既可以傳入const int也可以傳入int。 void fcn(int i){}//此時再寫一個函數定義,會報錯誤,因為重復定義了fcn(int)。傳引用參數:我們可以用非常量初始化一個底層const對象,但無法用一個底層const對象初始化一個非常量。如果形參是一個非常量,那么實參不能是一個底層const對象
同樣的初始化規則應用到參數傳遞上:
void reset(int *ip){...}void reset(int &i){...}string::size_type find_char(const string &s,char c,string::size_type &occurs){...}int i = 0;const int ci = i;string::size_type ctr = 0;reset(&i);//正確,調用形參類型是int*的reset函數。reset(&ci);//錯誤,不能用指向const int對象的指針初始化int*。reset(i);//正確,調用形參類型是int&的reset函數。reset(ci);//錯誤,不能把普通引用綁定到const對象ci上。reset(42);//錯誤,不能把普通引用綁定到字面值上。reset(ctr);//錯誤,類型不匹配find_char("hello world!",'o',ctr);//正確,find_char第一個形參是對常量的引用。盡量使用常量引用:
把函數不會改變的形參定義成普通的引用會給函數調用者一種誤導,即函數可以修改它實參的值。此外,使用引用而非常量引用也會極大限制函數所能接受實參類型。不能把const對象、字面值、或者需要類型轉換的對象傳遞給普通的引用形參。
string::size_type find_char(string &s,char c,string::size_type &occurs){...} find_char("hello world!",'o',ctr);//編譯時發生錯誤,因為不能把普通引用綁定到const對象上。應該把string &s修改為const string &sbool is_sentence(const string &s){string ::size_type ctr = 0;return find_char(s,'.',ctr) == s.size() - 1 && ctr == 1;//編譯時發生錯誤,因為s是常量引用,但find_char被定義成只接受普通引用。修改的話,需要改正find_char的形參,應該把find_char形參的string &s修改為const string &s }總結
- 上一篇: Linux Makefile
- 下一篇: c++primer 3.2,3.3练习题