什么是变量的引用
对一个数据可以使用“引用(reference)”,这是C++对C的一个重要扩充,引用是一种新的变量类型,它的作用是为一个变量起一个别名。假如有一个变量a,想给它起一个别名b,可以这样写:
inta; //定义a是整型变量
int&b=a; //声明b是a的引用
以上语句声明了b是a的引用,即b是a的别名。经过这样的声明后,a或b的作用相同,都代表同一变量。
注意:在上述声明中,&是引用声明符,并不代表地址。不要理解为“把a的值赋给b的地址”。声明变量b为引用类型,并不需要另外开辟内存单元来存放b的值。b和a占内存中的同一个存储单元,它们具有同一地址。声明b是a的引用,可以理解为:使变量b具有变量a的地址。
c++引用语法:
类型标识符 &引用名 = 目标变量名;
(1)&在此不是求地址运算,而是起标识作用。
(3)
声明引用时,必须同时对其进行初始化。
(4)引用声明完毕后,相当于目标
变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。
(5)对引用求地址,就是对目标
变量求地址。&ra与&a相等。即我们常说引用名是目标变量名的一个别名。别名一词好像是说引用不占据任何内存空间。
但是编译器在一般将其实现为const指针,即指向位置不可变的指针。即引用实际上与一般指针同样占用内存。
(6)
需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。
C++引用的用法:
1、传递可变参数
传统的c中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。
所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过
指针来实现的。比如,实现
两整数
变量值交换的c程序如下:
1
2
3
4
5
6
7
|
void swapint(
int
*a,
int
*b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
|
使用引用机制后,以上程序的c++版本为:
1
2
3
4
5
6
7
|
void swapint(
int
&a,
int
&b)
{
int temp;
temp=a;
a=b;
b=temp;
}
|
调用该函数的c++方法为:swapint(x,y); c++自动把x,y的地址作为
参数传递给swapint函数。
2、给函数传递大型对象
副本,也就是
参数传递时,对象无须复制。下面的例子定义了一个有限整数集合的类:
1
2
3
4
5
6
7
8
9
10
11
|
const int maxCard=100;
Class Set
{
int elems[maxCard];
//集合中的元素,maxCard表示集合中元素个数的最大值。
int card;
//集合中元素的个数。
public
:
Set(){card=0;}
//构造函数
friend Set operator*(Set,Set);
//重载运算符号*,用于计算集合的交集用对象作为传值参数
//friendSetoperator*(Set&,Set&)重载运算符号*,用于计算集合的交集用对象的引用作为传值参数
...
}
|
先考虑集合交集的实现
1
2
3
4
5
6
7
8
9
10
11
12
|
Set operator*(Set Set1,Set Set2)
{
Set res;
for
(inti=0;i<Set1.card;++i)
for
(intj=0;j>Set2.card;++j)
if
(Set1.elems[i]==Set2.elems[j]){
res.elems[res.card++]=Set1.elems[i];
break
;
}
return res;
}
|
每次使用*做交集运算时,整个集合都被复制,这样效率很低。我们可以用引用来避免这种情况。
1
2
3
4
5
6
7
8
9
10
11
12
|
Set operator*(Set&Set1,Set&Set2)
{
Set res;
for
(inti=0;i<Set1.card;++i)
for
(intj=0;j>Set2.card;++j)
if
(Set1.elems[i]==Set2.elems[j]){
res.elems[res.card++]=Set1.elems[i];
break
;
}
return res;
}
|
3.引用返回值
using namespace std;
using namespace std;
#include <iostream>
int& fun(int& a){
a++;
return a;
} //把a返回引用函数,也就是说这个fun()就是a的别名
int main(void){
int b =10;
fun(b); //同理,fun(b)就是b自增后的b的别名
cout << b <<endl;
return 0;
}