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);输出的地址就不一样了,这一点我没有弄明白,还请各路大神解释一下。谢谢。
欢迎拍砖