C 語言在函數間傳遞參數,有 call by value、call by pointer 兩種方式,而 C++ 則多了 call by reference。以下舉例說明這三種方式的差異。
1.call by value - 參數以值傳遞,函式可以存取參數,但不會改變主程式的變數內容。下面的 test() 函式,將於自動產生 int x = a; 之後才進入函式,所以無論test() 中的 x 值如何改變,都不會影響主程式的 a,即使主程式把 int a 改名為 int x,兩者仍是各自獨立的
void test(int x) {
x=100;
}
int main() {
int a = 5;
test(a);
}
2.call by pointer - 參數以變數的"位址值"傳遞(事實上還是傳值),函式可以存取指標參數,不會改變叫用程式的指標本身,但透過*存取指標所指向的空間,可改變指向空間的內容。
test1() 於自動產生 int* y = a; 之後進入函式,接著宣告了一個名為 newptr 的 int 指標,然後把參數 y 指標的內容設為 newptr,但返回主程式之後,a 指標的位址並不受影響,*a 的值仍指向 5 而非 100。call by pointer 其實仍是以值的方式來傳遞,只是傳的是個位址值(指標)
#include <iostream>
using namespace std;
void test1(int* y) {
int* newptr=new int(100);
y = newptr;
cout << y << ":" << *y << endl;
}
int main() {
int* a=new int(5);
test1(a);
cout << a << ":" << *a << endl;
return 0;
}
而 test2() 於自動產生 int* y = a; 之後進入函式,此時 *y 與 *a 是指向同一位置,所以執行 *y=50; 就等於改變了 *a,而 y=NULL 則對 a 並無影響
#include <iostream>
using namespace std;
void test2(int* y) {
*y=50;
y=NULL;
}
int main() {
int* a=new int(5);
test2(a);
cout << a << ":" << *a << endl;
return 0;
}
這也是 call by pointer 又被稱為 call by address 的原因,在還沒有 reference 之前,函式都是使用此方式來修改"指標參數所指向的內容"。
3.call by reference - reference 的符號是 &,此方式直接把主程式的變數交給函式使用,中間沒有隱含自動產生 int x = a; 或 int* y = a; 這類的步驟。以 call by reference 傳遞的參數,若無 const 修飾,函式中對參數內容的任何改變,就等於直接在改變主程式所對應的變數內容
#include <iostream>
using namespace std;
void test3(int (&x)[3], int& y) { //(&x)必需括號,因為[]比&優先權高
x[0]=4;
x[1]=5;
x[2]=6;
y=0;
}
int main() {
int a[] = {1,2,3};
int b=100;
test3(a,b);
cout << a[0] << " " << a[1] << " " << a[2] << endl;
cout << b << endl;
return 0;
}
由於 call by reference 傳遞快速(尤其是在傳遞物件時),函式中的程式碼亦比較簡明,所以常被程式設計師採用,若要保持 call by value 的安全性避免函式更動到主程式的變數內容,可在參數前加上 const 常數修飾字即可。
1.call by value - 參數以值傳遞,函式可以存取參數,但不會改變主程式的變數內容。下面的 test() 函式,將於自動產生 int x = a; 之後才進入函式,所以無論test() 中的 x 值如何改變,都不會影響主程式的 a,即使主程式把 int a 改名為 int x,兩者仍是各自獨立的
void test(int x) {
x=100;
}
int main() {
int a = 5;
test(a);
}
2.call by pointer - 參數以變數的"位址值"傳遞(事實上還是傳值),函式可以存取指標參數,不會改變叫用程式的指標本身,但透過*存取指標所指向的空間,可改變指向空間的內容。
test1() 於自動產生 int* y = a; 之後進入函式,接著宣告了一個名為 newptr 的 int 指標,然後把參數 y 指標的內容設為 newptr,但返回主程式之後,a 指標的位址並不受影響,*a 的值仍指向 5 而非 100。call by pointer 其實仍是以值的方式來傳遞,只是傳的是個位址值(指標)
#include <iostream>
using namespace std;
void test1(int* y) {
int* newptr=new int(100);
y = newptr;
cout << y << ":" << *y << endl;
}
int main() {
int* a=new int(5);
test1(a);
cout << a << ":" << *a << endl;
return 0;
}
而 test2() 於自動產生 int* y = a; 之後進入函式,此時 *y 與 *a 是指向同一位置,所以執行 *y=50; 就等於改變了 *a,而 y=NULL 則對 a 並無影響
#include <iostream>
using namespace std;
void test2(int* y) {
*y=50;
y=NULL;
}
int main() {
int* a=new int(5);
test2(a);
cout << a << ":" << *a << endl;
return 0;
}
3.call by reference - reference 的符號是 &,此方式直接把主程式的變數交給函式使用,中間沒有隱含自動產生 int x = a; 或 int* y = a; 這類的步驟。以 call by reference 傳遞的參數,若無 const 修飾,函式中對參數內容的任何改變,就等於直接在改變主程式所對應的變數內容
#include <iostream>
using namespace std;
void test3(int (&x)[3], int& y) { //(&x)必需括號,因為[]比&優先權高
x[0]=4;
x[1]=5;
x[2]=6;
y=0;
}
int main() {
int a[] = {1,2,3};
int b=100;
test3(a,b);
cout << a[0] << " " << a[1] << " " << a[2] << endl;
cout << b << endl;
return 0;
}
沒有留言:
張貼留言