代码运行环境:Win10 32bits Vs2013
引用不是新定义一个变量,而是给已存变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间,
类型&引用变量名(对象名)= 引用实体
int a = 10;
int &ra = a; //类型必须和引用实体是同种类型
int a = 10;
int &ra; //这条语句编译时会出错
int &ra = a;
int &rra = a;
C++语言规定,引用变量在定义的时候就必须初始化,也就是将引用变量与被引用对象进行绑定。而这种引用关系一旦确定就不允许改变,直到引用变量结束其生命期。
const int a = 10;
int &ra = a; //这条语句会出错,因为a是常量
const int &ra = a;
int &b = 10; //这条语句也会出错,因为10是常量
const int &b = 10;
下面再来看看这种情况
double d = 12.34;
int &rd = d; //这条语句会出错,类型不同
const int &rd = d;
不加const引用会出错的原因是,通过rd可以改 d的值,这是不被允许的,因此会编译出错。加上const之后,虽然类型不匹配,但是加上const之后,就变成了常引用,不能通过rd改变d的值,因此这是可以的。但是这种 引用会丢失数据,引用后rd的值为12。
int n3[3] = {2, 4, 6};
int (&rn3)[3] = n3; //引用一个包含3个int的数组
看起来有点怪异,
用typedef看一下,就很好理解了
int n3[3] = {2, 4, 6};
typedef int Int3[3];
Int3 &rn3 = n3;
引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以存在对指针的引用。
int i = 42;
int *p ;
int *&r = p; //r是对指针p的引用
要理解r的类型到底是什么,最简单的办法是从右向左阅读r的定义。离变量名最近的符号对变的类型有最直接的影响。
void Swap(int &left, int &right)
{
int temp = left;
left = right;
right = temp;
}
int &TestReturn(int &a)
{
a += 10;
return a;
}
接下来我们看一个有趣的代码
int &Add(int a, int b)
{
int c = a + b;
return c;
}
int main()
{
int &ret = Add(10,20);
cout <cout <
>
【运行结果】:
30
20380984
第一次的结果是正确的,但是第二次打印的结果时错误的,原因是因为返回的引用,是栈上的空间,我们都知道,系统收回栈上的空间,只是收回这块空间的使用权,如果不在用这块空间,这块空间的值是不会被改变的,当用这块空间的值时,这块空间就会被覆盖。第一次打印正确的原因是临时变量C的值先传给打印函数,然后函数进行入栈操作。第二次出错,是引用这块空间已经被用过了。
引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同,我们看一个代码来分析引用的底层实现。
int i = 10;
int &ra = i;
ra = 20;
VS2013反汇编查看源码对应的汇编代码的步骤是:调试->窗口->反汇编
反汇编如下:
int i = 10;
003E83A8 mov dword ptr [i],0Ah
int &ra = i;
003E83AF lea eax,[i]
003E83B2 mov dword ptr [ra],eax
ra = 20;
003E83B5 mov eax,dword ptr [ra]
003E83B8 mov dword ptr [eax],14h
return 0;
003E83BE xor eax,eax
在汇编代码中,ri的数据类型为dword,也就是说,ra在内存中占据4个字节的位置。所以,ra的确是一个变量,它存放的是被引用对象的地址。
由于通常情况下,地址是由指针变量存放的,我们再来看一个代码:
int i = 10;
int *p = &i;
*p = 20;
反汇编:
int i = 10;
009983A8 mov dword ptr [i],0Ah
int *p = &i;
009983AF lea eax,[i]
009983B2 mov dword ptr [p],eax
*p = 20;
009983B5 mov eax,dword ptr [p]
009983B8 mov dword ptr [eax],14h
return 0;
009983BE xor eax,eax
神奇的发现:
(1)只要将p换成ra,所得汇编代码与第一段所对应的汇编代码完全一样。所以,引用变量在功能上等于一个指针常量,即一旦指向某一个单元就不能在指向别处。
(2)在底层,引用变量由指针按照指针常量的方式实现。