vector傳遞參數
前幾天寫一個很簡單的c++程序,但是中間遇到了很有趣的問題,搞得我當時一頓懵,後來弄懂了,簡單總結一下。
話說到底是什麼問題呢?調用函數時,怎樣引入實參才能對實參本身改變內容,有時候你想當然的調用了函數func,func運行完,發現參數並沒有改變,這可如何是好?很簡單的一個問題,還請大神們不要嘲笑我這個大專生。
咱們以對數組的元素加一爲例,首先數組以兩種方式來表示,第一個是vector,第二個就是普通的數組int a[] = {}這兩種方式。接下來看第一種方式:
1 形參是實參的引用
/**
* 形參是對實參的引用, 所以形參怎麼變化, 實參就怎麼變化
* 而且有返回值, 返回啥就是啥, 實參的內容改變了
* 形參的內存地址和實參的內存地址是一樣的
* */
vector<int> add(vector<int> &a){
cout<<"引用數組的地址:"<<(void*)(&a)<<endl;
for (int i=0; i<a.size();i++){
a[i] += 1;
}
return a;
}
main函數如下:
int main(){
vector<int> a(6, 0);
a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
// int a[] = {1, 2, 3, 4, 5, 6};
vector<int> b = add(a);
cout<<(void*)(&a)<<endl;
// cout<<(void*)(&b)<<endl;
// sortInters2(b);
for (int num : a)
cout<<num<<" ";
cout<<endl;
for (int num : b)
cout<<num<<" ";
return 0;
}
結果如下:
首先看地址,原數組和引用數組的地址是一樣的,這其實十一句廢話,引用就是指向同一塊內存,對形參改變就是對內存中內容的改變,也就是對實參的改變,所以我的add函數還有必要有返回值嗎?沒必要了吧,
2 形參是實參的拷貝
/**
* 形參是實參的拷貝, 也就是形參把實參拷貝進來, 在內存多了一份a
* 而且有返回值, 返回的是拷貝的這一塊內存地址, 所以接收值內容改變了
* 形參的內存地址和實參的內存地址不一樣
* */
vector<int> add1(vector<int> a){
cout<<(void*)(&a)<<endl;
for (int i=0; i<a.size();i++){
a[i] += 1;
}
return a;
}
main函數如下:
int main(){
vector<int> a(6, 0);
a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
// int a[] = {1, 2, 3, 4, 5, 6};
vector<int> b = add1(a);
cout<<" 原數組的地址:"<<(void*)(&a)<<endl;
// cout<<(void*)(&b)<<endl;
// sortInters2(b);
for (int num : a)
cout<<num<<" ";
cout<<endl;
for (int num : b)
cout<<num<<" ";
return 0;
}
結果如下:
可以看到引用數組和原數組的內存地址不一樣,而且原數組的數值沒有變化,add函數返回的值變了。實際上,引用數組是對原是數組進行了一次拷貝,也就是add函數操作的是拷貝的那一塊內存,而原始數組根本沒有變化,但是add函數有返回值,如果不看內存,我們還以爲add函數真的作用在了原始數組上。你覺着樣這個函數是不是很作啊,多拷貝出來一塊內存,也不想想內存有多貴?顯然這樣做有些多餘。接着看下面例子
3 形參是實參的引用
emmmm?上面不是有一個這樣的標題了,小編你糊塗了。莫慌莫慌,且看代碼
/**
* 形參是實參的引用, 此時函數操作的是實參的內存地址, 雖然沒有返回值, 但是原來的內存對應的
* 數值是改變了的.
* 形參內存地址和實參內存地址一樣
* */
void add3(vector<int> &a){
cout<<"引用數組的地址:"<<(void*)(&a)<<endl;
for (int i=0; i<a.size();i++){
a[i] += 1;
}
}
上面函數沒有返回值的!!!
main函數代碼如下:
int main(){
vector<int> a(6, 0);
a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
// int a[] = {1, 2, 3, 4, 5, 6};
cout<<" 原數組的地址:"<<(void*)(&a)<<endl;
cout<<"調用函數前"<<endl;
for (int num : a)
cout<<num<<" ";
cout<<endl;
add3(a);
// sortInters2(b);
cout<<"調用函數後"<<endl;
for (int num : a)
cout<<num<<" ";
cout<<endl;
return 0;
}
結果如下:
沒有返回值,形參的地址和實參的地址是一塊內存,所以操作形參就是對實參的操作,對吧,這才符合我們的要求,沒有多餘的內存,一個引用就解決了問題。這個是推薦的做法!!!
4 數組怎樣來操作
/**
* 數組就相當於指針, 所以這個函數和上面那個函數是一致的
* */
void add2(int a[]){
// 此處爲什麼用&a就不行了
cout<<"引用數組的地址:"<<(void*)(a)<<endl;
for (int i=0;i<6; i++){
a[i] += 1;
}
}
main函數代碼如下:
int main(){
// vector<int> a(6, 0);
// a[0] = 9, a[1] = 8, a[2] = 7, a[3] = 6, a[4] = 4, a[5] = 3;
int a[] = {1, 2, 3, 4, 5, 6};
cout<<"調用函數前"<<endl;
for (int num : a)
cout<<num<<" ";
cout<<endl;
cout<<" 原數組的地址:"<<(void*)(&a)<<endl;
add2(a);
// sortInters2(b);
cout<<"調用函數後"<<endl;
for (int num : a)
cout<<num<<" ";
cout<<endl;
return 0;
}
結果如下所示:
看到了吧,形參和實參的地址是一致的,add函數沒有返回值,但是內容改變了,所以這個情況和上面一個情況是一樣的,所以這也是推薦的做法。
但是我有一個疑問,爲什麼我用
cout<<”引用數組的地址:”<<(void*)(&a);輸出的地址就不一樣了,這一點我沒有弄明白,還請各路大神解釋一下。謝謝。
歡迎拍磚