“引用”有时也称为“别名”,它是随C++引入的新概念,同时也是C++的重要特性。
最普通的引用定义,是书本上最常看到的,也是初学者最了解的:
int a; int &ra=a; //定义引用ra,它是变量a的引用,即变量a的别名
我们依次看一下,第一条语句执行后系统为变量a分配了一个int存储单元,第二条语句执行后系统为这个存储单元(变量a)起了个别名,从这时开始对引用ra的操作就完全等同于对变量a的操作;
注意:
(1) &在这里是定义语句的一部分,不是取地址的操作符;
(2) 引用的类型要和本源相同;int a; float &ra = a; 语句将会产生以下编译错误:error C2440: 'initializing' : cannot convert from 'int' to 'float &'
(3) 声明引用时,必须同时对其进行初始化;
(4) 不能建立数组的引用。因为数组是若干元素组成的集合,所以无法建立一个数组的别名。
至此我们已经了解引用的基本知识了,但是单纯的给某个变量取个别名简直是毫无意义的,我们必须知道引用可以做什么以及不可以做什么,但是鉴于本文仅仅是“浅谈”所以我决定仅仅阐述它最常用的几类应用。
一、引用作为参数
引用作为参数是一个很重要的应用,很多像我一样的初学者刚刚接触引用的时候,都只知道它有这个用途。我们知道C语言对于函数中的参数都是值传递的(如果需要传递大块数据或是要改变实参的值,我们会选择指针,但这仍然是值传递),而C++为我们提供了另一种选择,那就是引用。
使用引用作为参数可以避免产生实参的副本,这就意味着系统不再需要为参数压栈或是调用它的拷贝构造函数了[注1],因此使用引用作为参数不论在时间还是空间上都要好!与此同时,函数中对引用进行的操作就是对实参进行的操作,并且在主调函数的调用语句处也不需要再对变量进行特殊处理了(例如指针作为参数时,需要对变量进行取址&),因此使用引用作为参数不容易出错且代码的可读性要强!
二、引用作为“只读别名”
如果既要利用引用提高效率又不想数据被不小心修改,那就该使用常引用。常引用相当于给变量起了一个别名,并且通过这个别名访问变量时是只读的,从而达到了引用的安全性。关于常引用的定义以及保护数据的方法,我们来看这样一个例子:
注意代码中的var和ra都是常引用,编译器将会报错:
error C3892: 'var' : you cannot assign to a variable that is const
error C3892: 'ra' : you cannot assign to a variable that is const
三、引用作为返回值
引用作为返回值的定义格式:类型标识符 &函数名(形参列表) {函数体} eg. int &fun(int a, int b) {...}
说明
(1) 引用作为返回值,引用的是return后面的内容;例如:int &fun(int &r) {return r;} 函数将返回对r的引用;
(2) 使用引用返回函数值不会在内存中产生返回值的副本,这是引用作为返回值的最大好处;
注意
(1) 不能返回局部变量,因为当函数返回后局部变量将被销毁,如果继续引用局部变量的空间,程序的执行将变得不可预料;
(2) 不能返回函数内部用new分配的空间,因为当被引用的new空间是一个临时变量时,这段空间将无法释放,由此产生内存泄露;
四、引用实现多态
引用也可以像指针那样实现多态,也就是说基类的引用可以指向派生类的实例。如果基类中定义有虚函数,并且派生类中重写了这个虚函数,那么就可以通过基类的引用实现多态。
上述代码输出结果:This is Class B ..
注释:
[1]拷贝构造函数:当且仅当此参数为一个对象时,C++编译器调用拷贝构造函数完成一些基于同一类的其他对象的构建及初始化。
============================================================
此篇文章发表在这里仅仅是我个人对已掌握知识的梳理,最多也仅仅是浅谈而已,各位如果发现文章中有不准确的地方,欢迎批评指正!