c++新增了一种复合类型--引用变量。引用是已定义的变量的别名。(面试或笔试中也会常问道引用和指针的区别)常将引用变量用作函数的形参,函数将使用原始数据,而不是其拷贝,这点是不是和指针很像,确实很像,但同时又不同,让我们来具体看一看
c和c++中使用&符号来指示变量的地址。c++给&符号赋予了另一个含义,将其用来声明引用。例如,要将rodents作为rats变量的别名,可以这样做:
int rats;
int &rodents = rats;
上述引用声明允许将rats和rodents互换,他们指向相同的值和内存单元。
看一个简单的例子
#include <iostream>
int main()
{
using namespace std;
int ret = 100;
int & result = ret;
cout << "ret:" << ret << endl;
cout << "result:" << result << endl;
result++;
cout << "ret:" << ret << endl;
cout << "result:" << result << endl;
cout << "ret address:" << &ret << endl;
cout << "result address:" << &result << endl;
return 0;
}
运行结果
在代码中要区别一下&符号的使用,一个是声明引用的时候和另一个是取地址的时候。从结果中可以看出,ret和result的值和地址都是一样的。并且,result++使两个值都变化了。
引用看起来和指针很像,但还是有很多不一样的地方
1、引用必须在声明的时候就初始化,指针在初始化的可以不初始化。
2、使用的时候不一样,引用使用时和普通变量一样,例如上面的result,result本身就是表示value,而如果时地址的话则要通过* 来解除地址,再比如,下面这种情况
#include <iostream>
using namespace std;
struct stu{
char name[10];
int height;
};
int main()
{
struct stu stu1 = {"xiaoming",178};
struct stu & stu2 = stu1;
struct stu *stu3 = &stu1;
cout << "name: "<< stu1.name <<" height:" << stu1.height << endl;
cout << "name: "<< stu2.name <<" height:" << stu2.height << endl;
cout << "name: "<< stu3->name <<" height:" << stu3->height << endl;
}
结果:
结构体时,引用还是用“.”来获取结构体内成员,指针则是用"->"来获取。所以回到本文的第一句话引用是已定义的变量的别名,它确实只是已定义变量的一个其他的名字,使用上方法上和这个变量时一模一样的
引用更接近于const指针,必须在创建的时候初始化,一旦与某个变量关联起来,就将一直效忠于他。
int & result = res;
相当于
int * const reset = &res;
我们来看一个例子
#include <iostream>
int main()
{
using namespace std;
int ret = 100;
int & result = ret;
cout << "ret:" << ret << endl;
cout << "result:" << result << endl;
result++;
cout << "ret:" << ret << endl;
cout << "result:" << result << endl;
cout << "ret address:" << &ret << endl;
cout << "result address:" << &result << endl;
int bus = 55;
result = bus;
cout << "result" << result << endl;
cout << "ret:" << ret << endl;
cout << "bus:" << bus << endl;
cout << "result address:" << &result << endl;
cout << "ret address:" << &ret << endl;
cout << "bus address:" << &bus << endl;
return 0;
}
虽然我们启动修改引用result关联的变量,但是我们发现,尽管result打印的值发生了变化,但实际上,ret值也发生了变化,所以让一个引用指向另一个变量时,只会改变引用指向地址处的值,引用指向的地址时不会发生变化的。
简而言之,可以通过初始化声明来设置引用,但不能通过赋值。
再来看一个例子
#include <iostream>
int main()
{
using namespace std;
int ret = 100;
int *pt = &ret;
int & result = *pt;
cout << "ret:" << ret << endl;
cout << "result:" << result << endl;
int bus = 55;
pt = &bus;
cout << "result:" << result << endl;
cout << "ret:" << ret << endl;
cout << "bus:" << bus << endl;
cout << "result address:" << &result << endl;
cout << "ret address:" << &ret << endl;
cout << "bus address:" << &bus << endl;
return 0;
}
~
result引用关联了pt,pt指向的ret的地址,尽管pt后面指向了bus,但是result仍然时关联的ret.
引用变量经常被用作函数参数,使得函数中的变量名成为调用程序中的变量别名。这种传递参数的方法称为按引用传递。现在在c++中有了三种传递参数的方法,按值传递,按引用传递,按地址传递。我们通过下面一个程序来比较一下三者的区别。程序的作用是交换传递的两个参数的值
#include <iostream>
void swapr(int & a, int & b) // reference
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
void swapv(int a, int b) //value
{
int tmp;
tmp = a;
a = b;
b = tmp;
}
void swapp(int *a, int *b) //address
{
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
int main()
{
using namespace std;
int wallet1 = 300;
int wallet2 = 500;
cout << "wallet1: " << wallet1;
cout << " wallet2: " << wallet2 << endl;
cout << "using references to swap"<< endl;
swapr(wallet1,wallet2);
cout << "wallet1: " << wallet1;
cout << " wallet2: " << wallet2 << endl;
cout << "using pointers to swap"<< endl;
swapp(&wallet1,&wallet2);
cout << "wallet1: " << wallet1;
cout << " wallet2: " << wallet2 << endl;
cout << "using value to swap"<< endl;
swapv(wallet1,wallet2);
cout << "wallet1: " << wallet1;
cout << " wallet2: " << wallet2 << endl;
return 0;
}
执行结果:
从执行的结果可以看出:按地址和按引用传递,都可以改变这两个值,按值传递不能改变,从使用上来讲,按值传递和按引用传递在调用时的形态是一样,我们只能从函数的定义上才能区分出是按值传递还是按引用传递。