版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010853261/article/details/84929440
本文主要分析C++里面两大类函数传参方式:传值和传址(传引用和传指针)
1.传值
我们知道当我们调用一个函数时,OS会在内存中为这个函数建立起一块程序栈帧,这个栈帧提供了函数参数的存储空间。
对于传值这种方式,实际上是将函数参数进行了一次copy,传递到函数的实际上是变量的一个副本。在函数内部对参数进行的update不会影响到原本函数外的参数的值。
比如以下代码段:
#include <iostream>
using namespace std;
int add(int a, int added){
a = a + added*10;
return a;
}
int main(){
int x = 10;
int added = 2;
cout << add(x, added) << endl;
cout << "x=" << x << endl;
return 0;
}
程序的输出是:
30
x=10
由此可见add函数里面对x更改,并不会影响到函数外的变量x。所以当我们call函数的时候,实际上是将第一个入参copy了一份,然后assignment给局部变量a。
2.传址
传址在C++里面有两种:传引用(&)和传指针(*)。
2.1 Pass by Reference
reference扮演着外界与对象之间的一个间接手柄的角色。引用的声明是在类型名称和reference之间插入&符号。比如
int ival =1024;
int *pi = &ival;//代表指针变量
int & rval = ival;//代表引用变量。
上面的代码声明的变量rval就是代表一个引用,间接指向变量ival。
有一点需要特备注意:C++规定reference代表的对象在初始化的时候指定了之后不允许再更改,必须从一而终。也就是说如果一个一个reference已经初始化过了,后面的assignment都是copy操作。
当我们通过reference的方式将对象传递给函数的时候,对象本身并不会做一次copy,而是对对象的地址做了一个复制。函数中对对象的任何操作都相当于是对传入对象进行间接操作。
当我们使用pass by reference的时候,主要考虑两点:
- 希望对函数传递参数进行修改
- 降低复制大型对象的额外负担
现在对前面代码做一个很小的更改:
#include <iostream>
using namespace std;
int add(int &x, int added){
x = x + added*10;
return x;
}
int main(){
int x = 10;
int added = 2;
cout << add(x, added) << endl;
cout << "x=" << x << endl;
return 0;
}
···
这个时候的输出是:
> 30
> x=30
所以当我们pass by reference,函数会更改入参对象数据。
## 2.2 Pass by Pointer
传递指针和传递reference的区别其实并不大,下面是传递pointer的使用方式:
```cpp
#include <iostream>
using namespace std;
int add(int *x, int added){
*x = *x + added*10;
return *x;
}
int main(){
int x = 10;
int added = 2;
cout << add(&x, added) << endl;
cout << "x=" << x << endl;
return 0;
}
输出也是
30
x=30
2.3 the difference between passing a reference and a pointer
reference和pointer在使用上的功能几乎相同,但是有一个很重要的区别在于:
- pointer指向的对象可能(也可能不是)某个实际对象,也就是pointer可能指向某个null。
- 当我们提领pointer的时候,一定要先确认非0 ,否则会导致不可确定的严重错误。
- reference则必定会代表某个对象,所以不需要做这种非零检查。