按值传递
#include<iostream>
using namespace std;
int add(int r){
r++;
cout<<r<<endl;
return r;
}
int main(){
int a;
cin>>a;
cout<<a<<endl;
add(a);
cout<<a<<endl;
return 0;
}
运行结果如图所示:
在这里可以看出,按值传递函数对值进行的操作并不会影响外部变量。这是因为他们是存储在不同的空间中,函数操作的只是外部变量的一个副本。
那么如果需要让函数的操作作用于外部变量则需要通过指针传递或者引用传递;
指针传递
#include<iostream>
using namespace std;
int add(int *r){
cout<<"*r="<<*r<<endl;
(*r)++;//也可以写成++*r;
cout<<"*r="<<*r<<endl;
return 0;
}
int main(){
int a;
cin>>a;
cout<<"a="<<a<<endl;
add(&a);
cout<<"a="<<a<<endl;
return 0;
}
运行结果如图所示:
说明:add()函数中的形参是一个指针变量,将外部变量所存储的地址传入函数中之后,直接就会对外部变量产生改变。
(*r)++:自增运算符作为后缀的话比指针运算符的优先级高,因此需要加括号是要优先进行运算,先进行指向运算操作,再将这个值自增1;如果不加括号的话,会地址自增1,指向位置区域然后进行指向操作,得到该地址所存的内容,具有很大的不确定性。
++*r:自增运算符作为前缀的话比指针运算符的优先级相同,按从右向左的运算顺序进行结合,先进行指向操作再自增1.
按引用传递
#include<iostream>
using namespace std;
int add(int& a){
cout<<"a="<<a<<endl;
a++;
cout<<"a="<<a<<endl;
return 0;
}
int main(){
int m;
cin>>m;
add(m);
cout<<"m="<<m<<endl;
}
运行结果如下图所示:
说明:引用运算符和取地址运算符一样,除了在类型名后面的&是引用运算符的意思,其余地方都是取地址运算符。
这个add函数执行时不会再创建一个副本,函数收到的是一个别名,直接对本体进行操作。
C++中的引用可以理解为变量的一个别名,对引用的改动实际上就是对目标的改动;引用不是值,不会占用内存空间,引用只会有声明,而且声明时就要对其进行初始化——即指明引用的是哪个变量;因此不存在指向空值的引用。
引用与指针的区别:
1.可以存在空指针,但是不能存在空引用;
2.指针可以再使用过程中改变其指向的变量,而引用一旦定义好就无法改变其引用的值;
3.引用使用前不需要测试其合法性,而指针使用前总要测试其是否是空指针。
使用引用时要注意:不能建立引用的数组。