c++中,引用和指针时比较让人混淆的。它们的外在区别想必很多人都知道。在这我再重复一下。
引用在定义时必须初始化,即该引用所引用的必须时确实存在的变量,不能为NULL。而指针就没有这个限制。有人说,引用就相当于一个变量的别名,对该引用所做的操作就相当于对原变量一样。我不太认同这个看法。在内部实现上,其实引用也是通过地址实现的。因此我更想称引用为一种特殊的指针。让我们看看下面这个简单的例子。
#include<iostream.h>
int main()
{
int a=1;
int b=2;
int &c=a;
int *d=&b;
c=*d;
cout<<a<<endl;
cout<<c<<endl;
return 0;
}
反汇编代码如下:
1: #include<iostream.h>
2:
3: int main()
4: {
00401040 push ebp
00401041 mov ebp,esp
00401043 sub esp,50h
00401046 push ebx
00401047 push esi
00401048 push edi
00401049 lea edi,[ebp-50h]
0040104C mov ecx,14h
00401051 mov eax,0CCCCCCCCh
00401056 rep stos dword ptr [edi]
5: int a=1;
00401058 mov dword ptr [ebp-4],1
6: int b=2;
0040105F mov dword ptr [ebp-8],2
7: int &c=a;
00401066 lea eax,[ebp-4] !注意这里,把ebp-4赋给eax,ebp-4即为变量a的地址
00401069 mov dword ptr [ebp-0Ch],eax !把eax 存储在ebp-0Ch这个位置,ebp-0Ch为引用c的位置
8: int *d=&b;
0040106C lea ecx,[ebp-8]
0040106F mov dword ptr [ebp-10h],ecx !这两行和上面的两行是一模一样的
9: c=*d; !把b 的值赋给c
00401072 mov edx,dword ptr [ebp-0Ch] !把a的地址给edx
00401075 mov eax,dword ptr [ebp-10h] !把b的地址给eax
00401078 mov ecx,dword ptr [eax] !把b的值给ecx
0040107A mov dword ptr [edx],ecx !把ecx 即b的值给a,c引用的还是a
10: cout<<a<<endl;
0040107C push offset @ILT+10(endl) (0040100f)
00401081 mov edx,dword ptr [ebp-4]
00401084 push edx
00401085 mov ecx,offset cout (004299c0)
0040108A call ostream::operator<< (00401230)
0040108F mov ecx,eax
00401091 call @ILT+0(ostream::operator<<) (00401005)
11: cout<<c<<endl;
00401096 push offset @ILT+10(endl) (0040100f)
0040109B mov eax,dword ptr [ebp-0Ch]
0040109E mov ecx,dword ptr [eax]
004010A0 push ecx
004010A1 mov ecx,offset cout (004299c0)
004010A6 call ostream::operator<< (00401230)
004010AB mov ecx,eax
004010AD call @ILT+0(ostream::operator<<) (00401005)
12: return 0;
004010B2 xor eax,eax
13:
14: }
004010B4 pop edi
004010B5 pop esi
004010B6 pop ebx
004010B7 add esp,50h
004010BA cmp ebp,esp
004010BC call __chkesp (00403650)
004010C1 mov esp,ebp
004010C3 pop ebp
004010C4 ret
可见,在内部实现上,引用和指针是一模一样的,对引用的更改,就是把引用所指的变量重新赋指,引用本身并没有更改。