2.5.3 引用

引用类型在C++中被描述为变量的别名。实际上,C++为了简化指针操作,对指针的操作进行了封装,产生了引用类型。实际上引用类型就是指针类型,只不过它用于存放地址的内存空间对使用者而言是隐藏的。下面通过示例来揭开这个谜底,如代码清单2-8所示。

代码清单2-8 引用类型揭秘


//C++源码对比,定义int类型的变量并赋初始值0x12345678

int nVar=0x12345678;

0040E6F8 mov dword ptr[ebp-4],12345678h

//C++源码对比,定义变量nVar的引用类型nVarTpye

int&nVarTpye=nVar;

;取出变量nVar的地址并放入eax中

0040E6FF lea eax,[ebp-4]

;将变量nVar的地址存入地址ebp-8处,这个ebp-8处便是引用类型nVarTpye的地址

;从这条汇编语句中可以得出结论,引用类型在内存中是占有一席之地的

0040E702 mov dword ptr[ebp-8],eax

//调用函数Add, Add的参数为int引用类型,将变量nVar作为参数传递

Add(nVar);

//取出变量nVar的地址并放入ecx中

0040E705 lea ecx,[ebp-4]

;将ecx作为参数入栈,也就是传递变量nVar的地址作为参数

;关于函数参数的传递的讲解见第6章,函数Add实现见代码清单2-9

0040E708 push ecx

0040E709 call@ILT+15(Add)(00401014)

0040E70E add esp,4


在图2-10中可以发现,引用类型的存储方式和指针是一样的,都是使用内存空间存放地址值。所以,在C++中,引用和指针没有分别。只是引用是通过编译器实现寻址,而指针需要手动寻址。指针虽然灵活,但操作失误将产生严重的后果,而使用引用则不存在这种问题。因此,C++极力提倡使用引用类型,而非指针。

引用类型也可以作为函数的参数类型和返回类型使用。因为引用实际上就是指针,所以它同样会在参数传递时产生一份拷贝,如代码清单2-9所示。

代码清单2-9 引用类型作为函数参数


void Add(int&nVar){

;在Debug版中添加汇编代码略

nVar++;//C++源码对比,对引用类型nVar执行++操作

;取出参数nVar中的内容放入eax中

00401078 mov eax, dword ptr[ebp+8]

;对eax执行取内容操作

0040107B mov ecx, dword ptr[eax]

0040107D add ecx,1

00401080 mov edx, dword ptr[ebp+8]

00401083 mov dword ptr[edx],ecx

}

;在Debug版中添加汇编代码略

0040108B ret


在代码清单2-9中,通过对参数加1的方式修改了实参数据。从汇编代码中可以看出,引用类型的参数也占内存空间,其中保存的数据是一个地址值。取出这个地址中的数据并加1,再将加1后的结果放回。如果没有源码对照,指针和引用都一样难以区分。在反汇编下,没有引用这种数据类型。