C++ 函数 引用
一、引用的概念
引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。引用的声明方法:
类型标识符 &引用名 = 目标变量名;
为一个变量起一个别名。假如有一个变量a,想给它起一个别名b,可以这样写:
int a; //定义a是整型变量 int &b=a; //声明b是a的引用
二、引用的一些规则
(1)引用被创建的同时必须被初始化,指针则可以在任何时候被初始化。
(2)不能有NULL引用,引用必须与合法的存储单元关联,指针则可以是NULL。在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空。
(3)一旦引用被初始化,就不能改变引用的关系,但是指定的对象其内容可以改变。指针可以被重新赋值以指向另一个不同的对象。
例1:
void main() { int a1; int &ra; // error C2530: “ra”: 必须初始化引用 }
例2:
void main() { int a1, a2; int &ra = a1; int &ra = a2; // error C2374: “ra”: 重定义;多次初始化 }
企图使b又变成a2的引用(别名)是不行的。
例3:
int main() { int x=10; void &rx=x; // error C2182: “rx”: 非法使用“void”类型 int a[5]; int &ra[5]=a; // error C2234: “ra”: 引用数组是非法的 return 0; }
上例中的两处错误说明:void修饰是不能够声明引用的,引用是不能够声明数组的,即不能够声明引用数组。
在任何情况下都不能使用指向空值的引用,一个引用必须总是指向某些对象。因此如果使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时候应该把变量声明为指针,因为这样可以赋予空值给该变量。相反,如果变量肯定指向一个对象,这时候就可以把变量声明为引用。不存在指向空值的引用这个事实意味着使用引用的代码效率比指针要高。
三、常引用
常引用声明方式:
const 类型标识符 &引用名 = 目标变量名;
用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
例:
int main() { int a; const int &ra=a; ra=1; // error C3892: “ra”: 不能给常量赋值 a=1; // OK return 0; }
在C++面向对象程序设计中,经常用常指针和常引用作函数参数。这样既能保证数据安全,使数据不能被随意修改,在调用函数时又不必建立实参的拷贝。
四、引用之间的赋值
例:
int main() { int a = 1; int b = 2; printf("a = %d\n",a); printf("b = %d\n",b); printf("a address is:%d\n",&a); printf("b address is:%d\n",&b); printf("give reference for a and b\n"); int &ra = a; int &rb = b; printf("ra = %d\n",ra); printf("rb = %d\n",rb); printf("ra address is:%d\n",&ra); printf("rb address is:%d\n",&rb); printf("let ra = rb\n"); ra = rb; printf("a = %d\n",a); printf("b = %d\n",b); printf("ra = %d\n",ra); printf("rb = %d\n",rb); printf("a address is:%d\n",&a); printf("b address is:%d\n",&b); printf("ra address is:%d\n",&ra); printf("rb address is:%d\n",&rb); return 0; }
程序执行结果为:
a = 1
b = 2
a address is: 0031f870
b address is: 0031f864
give reference for a and b
ra = 1
rb = 2
ra address is: 0031f870
rb address is: 0031f864
let ra = rb
a = 2
b = 2
ra = 2
rb = 2
a address is: 0031f870
b address is: 0031f864
ra address is: 0031f870
rb address is: 0031f864
从上例可知,虽然引用被初始化后,便不能改变引用的关系;但是,可以用给它赋值其它引用。引用之间赋值并不改变引用和被引用变量的地址,只改变了引用对象值 。
五、指针的引用
指针的引用就是某一指针的一个别名,对引用的操作与对指针直接操作完全一样。指针引用的声明方法:
类型标识符 *&引用名 = 目标变量名;
在某种意义上,"*"和"&"是意思相对的两个东西,把它们放在一起有什么意义呢?。在某种程度上,指针的引用类似于二级指针(指针的指针)。
int main() { int x = 10; int *px = &x; //x的指针 int *& rpx = px; //x的指针的引用 int y = 20; int *py = &y; //y的指针 int *& rpy = py; //y的指针的引用 cout<<"x: "<<x<<endl cout<<"px:"<<px<<endl; cout<<"rpx: "<<rpx<<endl; cout<<"y: "<<y<<endl; cout<<"py:"<<py<<endl; cout<<"rpy: "<<rpy<<endl; cout<<"-------------------"<<endl; *rpx = *rpy; cout<<"x: "<<x<<endl; cout<<"px:"<<px<<endl; cout<<"rpx: "<<rpx<<endl; cout<<"y: "<<y<<endl; cout<<"py:"<<py<<endl; cout<<"rpy: "<<rpy<<endl; return 0; }
程序执行结果为:
x:10
px:0013FF60
rpx:0013FF60
y:20
py:0013FF3C
rpy:0013FF3C
-------------------
x:20
px:0013FF60
rpx:0013FF60
y:20
py:0013FF3C
rpy:0013FF3C
输出说明*rpx = *rpy之间的赋值并未改变指针引用的值,即地址的值,而是改变了引用对象的值 。
若将上例中*rpx = *rpy;改为:
rpx = rpy;
程序执行结果为:
x:10
px:0013FF60
rpx:0013FF60
y:20
py:0013FF3C
rpy:0013FF3C
-------------------
x:10
px: 0013FF3C
rpx: 0013FF3C
y:20
py:0013FF3C
rpy:0013FF3C
输出说明,指针引用之间的赋值只改变指针的值,引用对象的值没有改变
指针和引用
引用类型和指针类型都可以实现通过一个变量访问另一个变量,但访问的语法形式不同:
引用采用的是直接访问形式,指针采用间接访问形式。
除了在定义时指定的被引用变量外,引用类型变量不能再引用其它变量;而指针变量定义后可以指向其它同类型的变量。因此,引用类型比指针类型要安全。