C/C++中的引數傳遞方式
版權宣告:未經作者允許,嚴禁用於商業出版,否則追究法律責任。網路轉載請註明出處,這是對原創者的起碼的尊重!!!
1 傳值
C/C++預設的採用傳值,即在函式被呼叫的時候,給形參申請一個空間,再將實參的值傳遞給形參,對形參的任何改變不會影響實引數的值:
#include<iostream>
using namespace std;
int add(int x)
{
cout << "變化前,形式引數所在地址:" << &x << " " << "形式引數值:" << x << endl;
x++;
cout << "變化後,形式引數所在地址:" << &x << " " << "形式引數值:" << x << endl;
return 0;
}
int main()
{
int a = 1;
cout << "呼叫前,形式引數所在地址:" << &a << " " << "形式引數值:" << a << endl;
add(a);
cout << "呼叫後,形式引數所在地址:" << &a << " " << "形式引數值:" << a << endl;
return 0;
}
輸出結果如下:
可以看到形參實參的地址不一樣,說明新申請了記憶體空間。
可以看到對形參的操作不影響實參。
注:x是在函式內部定義的變數因而其作用範圍是區域性的(僅在該函式範圍內能訪問),生命週期是動態的(呼叫該函式時候建立,函式呼叫完成後就消除。)
2 傳址
2.1 傳指標
所謂傳址又叫做傳指標,即在函式被呼叫的時候,給形參開闢一個空間用來存放傳遞過來的地址,將實參所在的記憶體地址傳遞給形參,對形參的任何改變也不會影響實參所指的內容,但是對形參所指的內容的改變將會影響到實參所指的內容(因為這兩個指標都指向同一個記憶體空間)
#include<iostream>
using namespace std;
int fun(int *x,int *y)
{
cout << "變化前,指標x所在的地址:" << &x <<" 指標y所在地址:"<< &y <<endl;
cout << "變化前,指標x的值 :" << x << " 指標y的值 :" << y<<endl;
cout << "變化前,指標x所指的值 :" << *x<< " " <<" 指標y所指的值:"<< *y<<endl;
x++;
(*y)++;
cout << "變化後,指標x所在的地址:" << &x <<" 指標y所在地址:"<<&y<<endl;
cout << "變化後,指標x的值 :" << x <<" 指標y的值 :" << y<<endl;
cout << "變化後,指標x所指的值 :" << *x<< " " <<" 指標y所指的值:"<< *y<<endl;
return 0;
}
int main()
{
int n1 = 1,n2=1;
int *a = &n1;
int *b = &n2;
cout << "呼叫前,指標a所在的地址:" << &a <<" 指標b所在地址:"<<&b<<endl;
cout << "呼叫前,指標a的值 :" << a <<" 指標b的值 :" << b<<endl;
cout << "呼叫前,指標a所指的值 :" << *a<< " " <<" 指標b所指的值:"<< *b<<endl;
fun(a,b);
cout << "呼叫後,指標a所在的地址:" << &a <<" 指標b所å¨地址:"<<&b<<endl;
cout << "呼叫後,指標a的值 :" << a <<" 指標b的值 :" << b<<endl;
cout << "呼叫後,指標a所指的值 :" << *a<< " " <<" 指標b所指的值:"<< *b<<endl;
return 0;
}
執行下結果如下:
指標a和指標x所在地址不同說明新申請記憶體空間用以存放傳來的地址。
對指標x的值的改變不會改變指標a的值,也不會改變指標a所指的值,所以輸出結果為1。
對指標y所指的值的改變會改變指標b所指的值。所以輸出結果為2。
2.2 傳陣列
傳陣列是傳址的另一方式,陣列作為形參傳遞,實質傳遞的陣列的首地址,一維陣列形參 :資料型別 陣列名[]
,二維陣列形參:資料型別 陣列名[][上界]
。
注意:陣列在傳遞時會退化為指標,因而要傳入陣列長度。
3 傳引用
3.1 傳引用
引用是什麼?C++中的引用可以理解為typedef的作用(C中是沒有此用法),引用相當於是實參的別名,對形參的任何操作,就是對實參的操作,函式呼叫時不會再記憶體中新開闢空間。
#include<iostream>
using namespace std;
int add(int &x)
{
cout << "變化前,形式引數所在地址:" << &x << " " << "形式引數值:" << x << endl;
x++;
cout << "變化後,形式引數所在地址:" << &x << " " << "形式引數值:" << x << endl;
return 0;
}
int main()
{
int a = 1;
cout << "呼叫前,形式引數所在地址:" << &a << " " << "形式引數值:" << a << endl;
add(a);
cout << "呼叫後,形式引數所在地址:" << &a << " " << "形式引數值:" << a << endl;
return 0;
}
執行結果如下:
可以看到實參和形參的地址是相同的,也就是說並沒有開闢一個新的空間。對引用的操作就是對實參的操作。
3.2 傳指標的引用
其形式為function(資料型別* &指標名)
,這裡的指標名就是引用,就是傳來的指標的別名。對它的操作就是對實參指標的操作(類似於C中的二級指標。),對它所指的值的操作,就是對實參指標所指的值的操作。
#include<iostream>
using namespace std;
#define ok 0
int add(int* &x)
{
cout << "變化前指標x所在的地址: " << &x << endl;
cout << "變化前指標x的值 : " << x << endl;
cout << "變化前指標x所指的值 : " << *x << endl;
x++;
cout << "變化後指標x所在的地址: " << &x << endl;
cout << "變化後指標x的值 : " << x << endl;
cout << "變化後指標x所指的值 : " << *x << endl;
return ok;
}
int main()
{
int c = 1;
int *a = &c;
cout << "呼叫前指標a所在的地址:" << &a << endl;
cout << "呼叫前指標a的值 :" << a << endl;
cout << "呼叫前指標a所指的值 :" << *a << endl;
add(a);
cout << "呼叫後指標a所在的地址:" << &a << endl;
cout << "呼叫後指標a的值 :" << a << endl;
cout << "呼叫後指標a所指的值 :" << *a << endl;
return ok;
}
執行結果如下:
可以看到呼叫時沒有在記憶體中開闢空間儲存傳遞來的地址。對形參的改變就是對實參的改變。
4 總結
一般時候對傳入的實參如果要做改變,或傳入的資料非常大時候,C++中優先考慮傳引用(C/C++都可以傳址,然後對指標所指內容做改變),這樣呼叫函式時可以節約拷貝的時間和空間;如果對傳入的實參不做改變可以傳值、傳引用、傳址。
傳引用有些時候可以避免未初始化的錯誤。
#include<iostream>
using namespace std;
#define ok 0
struct linknode
{
int data;
linknode *next;
};
typedef linknode linklist;
int initlist(linklist *L)
{
L = (linknode*)malloc(sizeof(linknode));
return ok;
}
int main()
{
linklist* L;
initlist(L);
}
這裡由於在主函式定義了指標變數L後沒有初始化賦值,因而出現未初始化的錯誤。將int initlist(linklist *L)
改成int initlist(linklist *&L)
就可以免於此錯誤。
#include<iostream>
using namespace std;
#define ok 0
struct linknode
{
int data;
linknode *next;
};
typedef linknode linklist;
int initlist(linklist *L)
{
L = (linknode*)malloc(sizeof(linknode));
return ok;
}
int main()
{
linklist *L;
cout<<&L
initlist(L);
}
版權宣告:未經作者允許,嚴禁用於商業出版,否則追究法律責任。網路轉載請註明出處,這是對原創者的起碼的尊重!!!
相關文章
- C++引數的傳遞方式C++
- c++ -- 二維陣列引數傳遞C++陣列
- C,C++中如何向main(int argc , char argv[])傳遞引數C++AIGC
- java 傳遞引數的兩種方式Java
- java 中引數的傳遞Java
- C#引數傳遞之值引數C#
- 引數傳遞方式必須是const引用傳遞
- OFBiz中的引數傳遞
- 引數傳遞中編碼問題(Get/Post 方式)(一)
- 引數傳遞中編碼問題(Get/Post 方式)(二)
- Java中將方法作為引數傳遞5種方式Java
- ABAP 方法呼叫的引數傳遞裡,透過引用傳遞的方式,能修改原始引數值嗎?
- C#頁面間的引數傳遞C#
- C++ 預設引數與引用傳遞:語法、用法及示例C++
- 引數傳遞
- linux中main引數傳遞LinuxAI
- js中函式引數值傳遞和引用傳遞JS函式
- 面試官問:Go 中的引數傳遞是值傳遞還是引用傳遞?面試Go
- python中函式的引數傳遞Python函式
- c++單例模式、常量成員函式、引數傳遞、友元C++單例模式函式
- C# 中傳遞引數到執行緒的 N 個方法C#執行緒
- JS的方法引數傳遞(按值傳遞)JS
- c++指標傳遞與引用傳遞C++指標
- Mybatis傳遞多個引數的4種方式(乾貨)MyBatis
- JSP向後臺傳遞引數的四種方式JS
- JNI傳遞引數
- Mybatis引數傳遞MyBatis
- C# 多執行緒引數傳遞C#執行緒
- C++ 可變引數模板遞迴展開C++遞迴
- MyBatis 使用foreach與其他方式的時候引數傳遞方式MyBatis
- 請求引數的傳遞
- 函式的引數傳遞函式
- 從request中傳遞過來的引數資訊
- 獲取url中?後面傳遞的引數
- 【Practical Java】實踐1:引數以by value方式而非by reference方式傳遞Java
- React事件傳遞引數React事件
- 路由元件傳遞引數路由元件
- 說說不知道的Golang中引數傳遞Golang