C++语言中引用机制的实现分析
来源:互联网 发布:h5免费制作网站 知乎 编辑:程序博客网 时间:2024/05/20 21:57
C++语言中引用机制的实现分析
原文地址:http://blog.sina.com.cn/s/blog_6fd68d5f0100n5zy.html
一案例代码(VS2005 C++环境下调试)
#include <stdio.h>int& RefFun(int& n)//通过引用传递参数{n++;return n;}int ValueFun(int n)//通过变量值传递参数{n++;return n;}int main(int argc,char* argv[]){int a=10;int& x=a;//引用变量初始化int* pInt=&a;//取普通变量的地址int* pref=&x;//取引用变量的地址(其实获取的并不是引用变量的地址,而是被引用变量a的地址)int& b=RefFun(a);//函数返回引用,并将引用的别名赋值给引用变量int c=RefFun(a);//函数返回引用,并将引用变量的值赋值给整数变量int d=ValueFun(a);//函数返回变量值,printf("a=%d,b=%d,c=%d\n",a,b,c);return 0;}
二 对上面的Main函数反汇编代码分析
注:
1)以下是在VS2005下,使用C++工程进行调试(切换到反汇编模式)显示的代码;
2)每行源代码下面为其对应的汇编代码;
3)读者也可以在自己的VS2005开发平台下进行反汇编分析!
反汇编分析代码如下:
int main(int argc,char* argv[]){00411430 push ebp 00411431 mov ebp,esp 00411433 sub esp,114h 00411439 push ebx 0041143A push esi 0041143B push edi 0041143C lea edi,[ebp-114h] 00411442 mov ecx,45h 00411447 mov eax,0CCCCCCCCh 0041144C rep stos dword ptr es:[edi] int a=10;//对应的汇编代码:立即数寻址,给变量a赋值10,注意:dwordptr[a]为变量a的地址0041144E mov dword ptr [a],0Ah int& x=a;//引用变量初始化:其实质就是保存变量a的地址值到引用变量的内存单元!00411455 lea eax,[a] 00411458 mov dword ptr [x],eax int* pInt=&a;//取普通变量的地址0041145B lea eax,[a] //[a]表示变量a的地址;0041145E mov dword ptr [pInt],eax //变量a的地址保存到指针变量pInt中:这也是指针变量的原理;//下面的代码取引用变量的地址值,在实际很少用到该方式,在这里仅用于案例说明int* pref=&x;//取引用变量的地址(其实获取的并不是引用变量的地址,而是被引用变量a的地址)00411461 mov eax,dword ptr [x] //取引用变量内存单元保存的值(不是引用变量地址)00411464 mov dword ptr [pref],eax //引用变量内存单元值保存到指针变量;
//对上面两行源代码的汇编分析补充:
//1)[x]表示引用变量x内存单元地址,dwordptr[x]:表示内存单元X保存的值(实际是一个地址值,实际指向被引用的变量a的值);
//2)引用变量的实现秘密:引用变量在内部实现其实就是一个常量指针变量;
//3)分析上面取普通变量地址,与取引用的地址内部实现机理是不一样的;
int& b=RefFun(a);//函数返回引用,并将引用的别名赋值给引用变量00411467 lea eax,[a] //取变量a地址到EAX0041146A push eax //变量a的地址为:0x411159h0041146B call RefFun (411159h) //引用传递变量地址(指针)--引用实现的内部秘密!00411470 add esp,4 00411473 mov dword ptr [b],eax //EAX返回的为变量a的地址:实际为变量a的地址(初始化引用变量b)int c=RefFun(a);//函数返回引用,并将引用变量的值赋值给整数变量00411476 lea eax,[a] 00411479 push eax //变量a的地址入栈(传递给函数的引用参数实际是变量的地址)0041147A call RefFun (411159h) 0041147F add esp,4 00411482 mov ecx,dword ptr [eax] 00411484 mov dword ptr [c],ecx int d=ValueFun(a);//函数返回变量值,00411487 mov eax,dword ptr [a] //取变量a的值送到EAX寄存器0041148A push eax //变量a的值入栈(传递给函数:ValueFun);0041148B call ValueFun (4110DCh) 00411490 add esp,4 00411493 mov dword ptr [d],eax printf("a=%d,b=%d,c=%d\n",a,b,c);00411496 mov esi,esp 00411498 mov eax,dword ptr [c] 0041149B push eax 0041149C mov ecx,dword ptr [b] 0041149F mov edx,dword ptr [ecx] 004114A1 push edx 004114A2 mov eax,dword ptr [a] 004114A5 push eax 004114A6 push offset string "a=%d,b=%d,c=%d\n" (41563Ch) 004114AB call dword ptr [__imp__printf (4182B8h)] 004114B1 add esp,10h 004114B4 cmp esi,esp 004114B6 call @ILT+305(__RTC_CheckEsp) (411136h) return 0;004114BB xor eax,eax }
三代码实现分析---变量值传递参数&引用传递参数的区别
1对上面案例代码引用传递参数的RefFun分析--反汇编分析
int& RefFun(int& n)//通过引用传递参数{004113A0 push ebp 004113A1 mov ebp,esp 004113A3 sub esp,0C0h 004113A9 push ebx 004113AA push esi 004113AB push edi 004113AC lea edi,[ebp-0C0h] 004113B2 mov ecx,30h 004113B7 mov eax,0CCCCCCCCh 004113BC rep stos dword ptr es:[edi] n++;//简单的一个加1对应5行汇编代码(下面的传值函数,只有3行,这是区别所在)//下面为对应的汇编代码,注意与下面函数ValueFun通过变量值传递参数的方式区别:004113BE mov eax,dword ptr [n] //eax保存传递过来引用变量的地址值004113C1 mov ecx,dword ptr [eax] //取到传递过来的变量值004113C3 add ecx,1 004113C6 mov edx,dword ptr [n] //引用变量的地址保存到EDX004113C9 mov dword ptr [edx],ecx //保存加1后的结果;return n;//由于变量n保存的为变量的地址,因此这里返回的是传递进来的地址值(区别于传值)004113CB mov eax,dword ptr [n] }
2对上面案例代码引用传递参数的ValueFun分析--反汇编分析
int ValueFun(int n)//通过变量值传递参数{004113F0 push ebp 004113F1 mov ebp,esp 004113F3 sub esp,0C0h 004113F9 push ebx 004113FA push esi 004113FB push edi 004113FC lea edi,[ebp-0C0h] 00411402 mov ecx,30h 00411407 mov eax,0CCCCCCCCh 0041140C rep stos dword ptr es:[edi] n++;//对应的汇编代码(只有3行汇编代码,比上面的引用传递参数,相对简单):0041140E mov eax,dword ptr [n] //dwordptr[n]为栈上的临时变量n的地址;00411411 add eax,1 00411414 mov dword ptr [n],eax return n;//对应的汇编代码:返回的是栈上变量的值(这一点区别于引用,引用返回地址)00411417 mov eax,dword ptr [n] }
四 引用的实现秘密
通过对上面二,三章代码的反汇编代码的实现分析,对于引用变量的内部实现,可以得出如下结论:1)引用的内部实现为相当于一个指针变量,与指针的实现方式类似;
2)引用变量内存单元保存的指向变量地址(初始化时赋值),与指针不同地方时,引用变量在定义时必须初始化,而且使用过程中,引用变量保存的内存单元地址值是不能改变的(这一点通过编译器来实现保证);
3)引用也可以进行取地址操作,但是取地址操作返回的不是引用变量所在的内存单元地址,而是被引用变量本身所在的内存单元地址;
4)引用的使用,在源代码级相当于普通的变量一样使用,但在函数参数传递引用变量时,内部传递的实际是变量的地址值(这种机制的实现是通过编译器(编译手段)来实现的)。
0 0
- C++语言中引用机制的实现分析
- C++语言中引用机制的实现分析
- c语言引用传递的机制
- c语言指针和引用实现原理深入分析
- C语言中引用的用法
- 深入分析C语言中结构体指针的定义与引用详解
- C语言底层调用的实现机制
- C语言可变参数的实现机制
- python 中引用c语言
- Python实现的C语言词法分析
- 栈的引用--迷宫算法(c语言实现)
- python 像C语言样的函数参数引用实现..
- C中const的实现机制
- C/C++中const的实现机制
- C语言中基本数据类型的分析
- C语言中结构体指针的定义和引用
- C语言中结构体指针的定义和引用
- c语言中引用和传值的区别
- HTML5+ plus.maps地图详解(官方文档)
- 资本运作下的腾讯和帝国梦想
- quartz实现定时任务调度
- 注册nessus试用注册码
- 黑马程序员(认识IOS)
- C++语言中引用机制的实现分析
- POJ2724 Purifying Machine二分图,最小边覆盖
- 二叉查找树(二叉排序树)的详细实现,以及随机平衡二叉查找树Treap的分析与应用
- poj-1436
- 安卓调用webService技巧
- [编程之美] PSet3.3 计算字符串的相似度
- 数组
- Word Break
- httpurlconnection post 和GET 分别传递2个参数给后台,返回JSON 解决乱码问题