C编程复合数据类型引用

我们可以在C++中为数据对象另外起一个名字,这叫做“引用”(reference)。

1.引用的用法

在做声明时,我们可以在变量名前加上“”符号,表示它是另一个变量的引用。引用必须被初始化。

inta=10;

intref=a;//ref是a的引用

//intref2;//错误,引用必须初始化

cout"ref="refendl;//ref等于a的值

cout"a的地址为:"aendl;

cout"ref的地址为:"refendl;//ref和a的地址完全一样

引用本质上就是一个“别名”,它本身不是数据对象,所以本身不会存储数据,而是和初始值“绑定”(bind)在一起,绑定之后就不能再绑定别的对象了。

定义了应用之后,对引用做的所有操作,就像直接操作绑定的原始变量一样。所以,引用也是一种间接访问数据对象的方式。

ref=20;//更改ref相当于更改a

cout"a="aendl;

intb=26;

ref=b;//ref没有绑定b,而是把b的值赋给了ref绑定的a

cout"a的地址为:"aendl;

cout"b的地址为:"bendl;

cout"ref的地址为:"refendl;

cout"a="aendl;

当然,既然是别名,那么根据这个别名再另起一个别名也是可以的:

//引用的引用

intrref=ref;

cout"rref="rrefendl;

cout"a的地址为:"aendl;

cout"ref的地址为:"refendl;

cout"rref的地址为:"rrefendl;

“引用的引用”,是把引用作为另一个引用的初始值,其实就是给原来绑定的对象又绑定了一个别名,这两个引用绑定的是同一个对象。

要注意,引用只能绑定到对象上,而不能跟字面值常量绑定;也就是说,不能把一个字面值直接作为初始值赋给一个引用。而且,引用本身的类型必须跟绑定的对象类型一致。

//intref2=10;//错误,不能创建字面值的引用

doubled=3.14;

//intref3=d;//错误,引用类型和原数据对象类型必须一致

2.对常量的引用

可以把引用绑定到一个常量上,这就是“对常量的引用”。很显然,对常量的引用是常量的别名,绑定的对象不能修改,所以也不能做赋值操作:

constintzero=0;

//intcref=zero;//错误,不能用普通引用去绑定常量

constintcref=zero;//常量的引用

//cref=10;//错误,不能对常量赋值

对常量的引用有时也会直接简称“常量引用”。因为引用只是别名,本身不是数据对象;所以这只能代表“对一个常量的引用”,而不会像“常量指针”那样引起混淆。

常量引用和普通变量的引用不同,它的初始化要求宽松很多,只要是可以转换成它指定类型的所有表达式,都可以用来做初始化。

constintcref2=10;//正确,可以用字面值常量做初始化

inti=35;

constintcref3=i;//正确,可以用一个变量做初始化

doubled=3.14;

constintcref4=d;//正确,d会先转成int类型,引用绑定的是一个“临时量”

这样一来,常量引用和对变量的引用,都可以作为一个变量的“别名”,区别在于不能用常量引用去修改对象的值。

intvar=10;

intr1=var;

constintr2=var;

r1=25;

//r2=35;//错误,不能通过const引用修改对象值

3.指针和引用

从上一节中可以看到,常量引用和指向常量的指针,有很类似的地方:它们都可以绑定/指向一个常量,也可以绑定/指向一个变量;但不可以去修改对应的变量对象。所以很明显,指针和引用有很多联系。

(1)引用和指针常量

事实上,引用的行为,非常类似于“指针常量”,也就是只能指向唯一的对象、不能更改的指针。

inta=10;

//引用的行为,和指针常量非常类似

intr=a;

int*constp=a;

r=20;

*p=30;

cout"a="aendl;

cout"a的地址为:"aendl;

cout"r="rendl;

cout"r的地址为:"rendl;

cout"*p="*pendl;

cout"p="pendl;

可以看到,所有用到引用r的地方,都可以用*p替换;所有需要获取地址r的地方,也都可以用p替换。这也就是为什么把操作符*,叫做“解引用”操作符。

(2)指针的引用

指针本身也是一个数据对象,所以当然也可以给它起别名,用一个引用来绑定它。

inti=56,j=28;;

int*ptr=i;//ptr是一个指针,指向int类型对象

int*pref=ptr;//pref是一个引用,绑定指针ptr

pref=j;//将指针ptr指向j

*pref=20;//将j的值变为20

pref是指针ptr的引用,所以下面所有的操作,pref就等同于ptr。

可以有指针的引用、引用的引用,也可以有指向指针的指针;但由于引用只是一个“别名”,不是实体对象,所以不存在指向引用的指针。

intref=i;

//int*rptr=ref;//错误,不允许使用指向引用的指针

int*rptr=ref;//事实上就是指向了i

(3)引用的本质

引用类似于指针常量,但不等同于指针常量。

指针常量本身还是一个数据对象,它保存着另一个对象的地址,而且不能更改;而引用就是“别名”,它会被编译器直接翻译成所绑定的原始变量;所以我们会看到,引用和原始对象的地址是一样,引用并没有额外占用内存空间。这也是为什么不会有“指向引用的指针”。

引用的本质,只是C++引入的一种语法糖,它是对指针的一种伪装。

指针是C语言中最灵活、最强大的特性;引用所能做的,其实指针全都可以做。但是指针同时又令人费解、充满危险性,所以C++中通过引用来代替一些指针的用法。后面在函数部分,我们会对此有更深刻的理解。




转载请注明:http://www.aierlanlan.com/rzdk/5632.html