C++中有一种新的变量叫做引用变量。引用变量就是其他变量的别名,如同一个人的外号,同时外号也指那个人。比如:
inta=3;
intr=a;//r在这里就是引用变量,它的类型是int。也就是:int型的引用变量r引用的是变量a,也就是说r是a的别名。r和a是同一个东西。
一.需要注意的点:
1.引用变量是“从一而终”的,也就是说一旦定义了引用变量就不能再定义同名的引用变量去引用其他的变量。比如
intr=a;
intr=b;//错误原因:引用变量r同时引用了a,b
2.引用变量和被引用的变量类型必须匹配。比如
doubled;
intr=d;//错误原因:int类型的引用变量r不能引用double类型的变量d。它两个类型不匹配。
3.对引用变量的操作实质就是对它引用的变量的操作,很好理解,比如:
inta=3,r=a;//r引用了a
r=5;//对引用变量r进行操作
couta’t’rendl;//a,r的结果都是5。因为r和a是同一个内存块的名字。
二.引用变量的用途
主要是用作函数的形参。
1.问题的举例
传统C语言函数的参数叫形参。它是一种值参数,就是说C函数的形参都是值参数,形参作为函数的局部变量有着自己单独的内存块,当函数调用的时候,我们会将实参通过值拷贝的方式拷贝给形参,将来在这个被调用的函数里对形参的修改,不会引用实参,也不会改变实参的值。我们看一个具体例子:
#includeiostream
usingnamespacestd;
voidswap(intx,inty){
intt=x;
x=y;
y=t;
}
intmain(){
inta=3,b=4;
couta‘\t’bendl;
swap(a,b);
couta‘\t’bendl;
}
main函数里面有两个变量a,b,然后输出一下,然后调用swap函数把a,b传输给swap函数的x,y(形参),最后输出a,b。
详细分析:在我们执行main函数的时候,C/C++程序都会有一个程序堆栈,用来存放它的局部变量,比如这里的a,b。在这个程序的堆栈里有两块内存,一个是a,一个是b,分别是3和4。当我们第一次输出的时候,输出的是3,4的值。接着,调用swap函数,把a,b两个实参传给形参x,y。那它怎么传呢?就是把a的值拷贝到swap函数的局部变量x里面,b拷贝到y里面。swap函数的x,y是两个执行栈,也就是它们也有着自己单独的内存块,所以在这里我们就把a拷贝到swap函数的x,b拷贝到swap函数的y。此外,swap函数还有另外一个变量t。这个时候,程序的堆栈的最上面就是swap函数的局部变量x,y,t,就是说程序的堆栈最上面放的总是当前正运行的函数的局部变量。此时,当前正运行的函数是swap函数,它有三个变量x,y,t。然后再执行t=x,本来t没有值,现在变成了3。当函数执行完之后,它在堆栈区的局部变量占用的数据就会弹出堆栈,所谓弹出堆栈就是从堆栈里出来了,就没了(这里x,y,t没了)。因为一个函数或者程序块执行结束后,它的局部变量就销毁不存在了。swap函数运行结束,程序又跳到main函数里面了,这个时候我们看堆栈区就剩main函数的局部变量,表示当前执行的是main函数,那么这里输出的a,b仍然是刚才的值,所以它的结果未发生改变。
2.C语言解决办法
我们发现swap函数里面x,y是发生交换的。也就是说对于这种值参数,我们在形式参数里面对x,y确实进行了修改,但是x,y的修改并不会影响实际参数的值,所以,这就是函数的值形参x,y的特点。基于这个问题,C语言的解决方法,如下:
#includeiostream
usingnamespacestd;
voidswap(int*x,int*y){
intt=*x;
*x=*y;
*y=t;
}
intmain(){
inta=3,b=4;
couta‘\t’bendl;
swap(a,b);
couta‘\t’bendl;
}
为了使得这个a,b交换,我们在C语言里面,通常要把a,b的地址传给swap函数,所以,swap函数的函数形式,也就是里面的参数类型就要变了,x,y就不是两个整型变量,而需要用到int指针类型,也就是整型变量的地址。也就是说x保存的是整型变量a的地址。如图
假如a的地址是0x3b10,此时就放在了x里面了。当我们执行函数调用的时候,就把a的地址拷贝到x内存块里面,b的地址拷贝到y的内存块里面。然后我们再执行,t=*x,x是地址,*x是取内容,这里*x就是a,把a的值赋值到t里面去。*在这里是取内容运算符(关于*的作用:当运算符的时候,表示取内容或乘法运算;作为变量定义的时候,比如int*x,表示的是定义一个指针变量。所以说*在定义变量和作为运算符时候,它的含义是不一样的)。
这样,我就通过x,y(地址)分别指向的a,b来对a,b两个内存块进行操作,使得a,b的内容发生修改了,这是我们在C语言里是这样做的,我们通过传递指针变量给值参数x,y,然后通过这个指针间接去访问a,b,最终达到修改a,b内存中的数据的目的。当swap执行完之后,x,y,t这三个变量也会被销毁了。虽然销毁了,但是a,b之前已经修改了。
3.C++解决办法
C++引入一个新的变量叫引用变量,那么对于函数的形参也可以把它定义成引用型的变量,在定义形参的时候不需要对它初始化,因为它是作为形参,将来初始化时用实参来对它初始化。代码如下:
#includeiostream
Usingnamespacestd;
voidswap(intx,inty){
intt=x;
x=y;
y=t;
}
intmain(){
inta=3,b=4;
couta‘\t’bendl;
swap(a,b);
couta‘\t’bendl;
}
这里,swap在定义变量x,y的时候,前面加符号,说明x,y是一个引用变量,也就是引用的形参,将来x,y分别引用调用这个函数的两个实参。也就是说在main函数里面调用swap函数时,x就引用a,也就是说x就是a的别名,y就是b的别名。而x,y这里并没有单独的内存块。如图
这样就达到交换实参的目的。
点睛:引用形参,也就是形参是一个引用变量
总结:引用变量作为函数的形参可以通过引用形参去引用实际变量,在调用的函数里面对引用形参的修改,实际上修改的就是实际参数。