C++对象作为函数参数 http://blog.csdn.net/tms_li/article/details/7765626
来源:互联网 发布:王学圻 范冰冰 知乎 编辑:程序博客网 时间:2024/05/16 03:18
C++对象作为函数参数 2014-06-10 09:26:51
分类: C/C++
关于C/C++中基本类型(如:int,int*等)作为函数参数时,是通过将该变量的值压栈来进行参数传递;本文通过C++反汇编代码分析了当对象作为函数参数时(该形参非引用或指针),参数如何传递以及此时栈帧的结构。
对象作为函数参数时,参数传递过程(如:函数的声明为:void show(class Object obj);该函数的调用的为show(arg);其中实参arg的类型为class Object):1,在栈顶上为obj对象分配内存空间,然后将对象arg的首地址压栈;2,调用拷贝构造函数(此为C++中三种调用拷贝构造函数情况之一),将arg的数据成员拷贝至obj;3,执行show()函数体(此时,ebp+8即为obj的首地址)。
具体分析过程,见代码注释。
点击(此处)折叠或打开
- //C++源码。
- //VC6.0
- #include<iostream>
- #include<cstdio>
- using namespace std;
- class CBase{
- int i;
- public:
- CBase(int i=0)
- {
- this->i=i;
- }
- CBase(CBase& rhs) //拷贝构造函数。
- {
- i=rhs.i;
- printf("拷贝构造函数=%d\n",i);
- }
- void show(CBase B1, CBase B2) //对象作为形参。
- {
- printf("show=%d,%d\n",B1.i,B2.i);
- }
- };
- int main()
- {
- CBase Base;
- CBase Basex(1);
- CBase Basexx(2);
- Base.show(Basex,Basexx);
- // printf("this is an end!\n");
- }
- ---------------------------------------------------------------------------------
- //main函数对应的汇编代码。
- int main()
- 24: {
- 0040D4A0 push ebp
- 0040D4A1 mov ebp,esp
- 0040D4A3 sub esp,54h
- 0040D4A6 push ebx
- 0040D4A7 push esi
- 0040D4A8 push edi
- 0040D4A9 lea edi,[ebp-54h]
- 0040D4AC mov ecx,15h
- 0040D4B1 mov eax,0CCCCCCCCh
- 0040D4B6 rep stos dword ptr [edi]
- 25: CBase Base;
- 0040D4B8 push 0
- 0040D4BA lea ecx,[ebp-4] //ecx保存的是对象Base的this指针。
- 0040D4BD call @ILT+0(CBase::CBase) (00401005)//调用构造函数
- 26: CBase Basex(1);
- 0040D4C2 push 1
- 0040D4C4 lea ecx,[ebp-8] //ecx保存的是对象Basex的this指针。
- 0040D4C7 call @ILT+0(CBase::CBase) (00401005)//调用构造函数
- 27: CBase Basexx(2);
- 0040D4CC push 2
- 0040D4CE lea ecx,[ebp-0Ch] //ecx保存的是对象Basexx的this指针。
- 0040D4D1 call @ILT+0(CBase::CBase) (00401005)//调用构造函数
- 28: Base.show(Basex,Basexx);
- 0040D4D6 push ecx //等价于esp=esp-4;
- 0040D4D7 mov ecx,esp //ecx保存的是show函数的形参B2的this指针。
- 0040D4D9 lea eax,[ebp-0Ch]
- 0040D4DC push eax //对Basexx的this(即Basexx对象的首地址)指针压栈。
- 0040D4DD call @ILT+10(CBase::CBase) (0040100f)//调用拷贝构造函数
- 0040D4E2 push ecx //等价于esp=esp-4;
- 0040D4E3 mov ecx,esp //ecx保存的是show函数的形参B1的this指针。
- 0040D4E5 lea edx,[ebp-8]
- 0040D4E8 push edx //对Basex的this(即Basex对象的首地址)指针压栈。
- 0040D4E9 call @ILT+10(CBase::CBase) (0040100f)//调用拷贝构造函数
- 0040D4EE lea ecx,[ebp-4] //ecx保存的是Base对象的this指针。
- 0040D4F1 call @ILT+20(CBase::show) (00401019)//调用show函数。
- 29: printf("this is an end!\n");
- 0040D4F6 push offset string "this is an end!\n" (00422fa4)
- 0040D4FB call printf (0040d7c0)
- 0040D500 add esp,4
- 30: }
- 0040D503 pop edi
- 0040D504 pop esi
- 0040D505 pop ebx
- 0040D506 add esp,54h
- 0040D509 cmp ebp,esp
- 0040D50B call __chkesp (004010b0)
- 0040D510 mov esp,ebp
- 0040D512 pop ebp
- 0040D513 ret
- //show函数对应的汇编代码。
- 16: void show(CBase B1,CBase B2)
- 17: {
- 0040D550 push ebp
- 0040D551 mov ebp,esp
- 0040D553 sub esp,44h
- 0040D556 push ebx
- 0040D557 push esi
- 0040D558 push edi
- 0040D559 push ecx
- 0040D55A lea edi,[ebp-44h]
- 0040D55D mov ecx,11h
- 0040D562 mov eax,0CCCCCCCCh
- 0040D567 rep stos dword ptr [edi]
- 0040D569 pop ecx
- 0040D56A mov dword ptr [ebp-4],ecx
- 18: printf("show=%d,%d\n",B1.i,B2.i);
- 0040D56D mov eax,dword ptr [ebp+0Ch] //ebp+0Ch对应的是B2的首地址。
- 0040D570 push eax
- 0040D571 mov ecx,dword ptr [ebp+8] //ebp+8h对应的是B1的首地址。
- 0040D574 push ecx
- 0040D575 push offset string "show=%d,%d\n" (00422fcc)
- 0040D57A call printf (0040d7c0)
- 0040D57F add esp,0Ch
- 19: }
- 0040D582 pop edi
- 0040D583 pop esi
- 0040D584 pop ebx
- 0040D585 add esp,44h
- 0040D588 cmp ebp,esp
- 0040D58A call __chkesp (004010b0)
- 0040D58F mov esp,ebp
- 0040D591 pop ebp
- 0040D592 ret 8
- //拷贝构造函数对应的汇编代码(注释略)。
- 11: CBase(CBase& rhs)
- 0040D840 push ebp
- 0040D841 mov ebp,esp
- 0040D843 sub esp,44h
- 0040D846 push ebx
- 0040D847 push esi
- 0040D848 push edi
- 0040D849 push ecx
- 0040D84A lea edi,[ebp-44h]
- 0040D84D mov ecx,11h
- 0040D852 mov eax,0CCCCCCCCh
- 0040D857 rep stos dword ptr [edi]
- 0040D859 pop ecx
- 0040D85A mov dword ptr [ebp-4],ecx
- 12: {
- 13: i=rhs.i;
- 0040D85D mov eax,dword ptr [ebp-4]
- 0040D860 mov ecx,dword ptr [ebp+8]
- 0040D863 mov edx,dword ptr [ecx]
- 0040D865 mov dword ptr [eax],edx
- 14: printf("拷贝构造函数=%d\n",i);
- 0040D867 mov eax,dword ptr [ebp-4]
- 0040D86A mov ecx,dword ptr [eax]
- 0040D86C push ecx
- 0040D86D push offset string "\xbf\xbd\xb1\xb4\xb9\xb9\xd4\xec\xba\xaf\xca\xfd=%d\n" (00422fb8)
- 0040D872 call printf (0040d7c0)
- 0040D877 add esp,8
- 15: }
- 0040D87A mov eax,dword ptr [ebp-4]
- 0040D87D pop edi
- 0040D87E pop esi
- 0040D87F pop ebx
- 0040D880 add esp,44h
- 0040D883 cmp ebp,esp
- 0040D885 call __chkesp (004010b0)
- 0040D88A mov esp,ebp
- 0040D88C pop ebp
- 0040D88D ret 4
当执行show函数作用域内代码时,栈结构图示如下:
0 0
- C++对象作为函数参数 http://blog.csdn.net/tms_li/article/details/7765626
- C++愤恨者札记1——类对象作为函数参数的数据传递过程 http://blog.csdn.net/tms_li/article/details/7765626
- system()函数 http://blog.csdn.net/ghevinn/article/details/7916126
- 虚函数 http://blog.csdn.net/zhouyayong09/article/details/9100667
- 链表 C http://blog.csdn.net/pf4919501/article/details/38818335
- c语言中time函数的用法 http://blog.csdn.net/wangluojisuan/article/details/7045592
- c++中临时变量不能作为非const的引用参数http://blog.csdn.net/kongying168/article/details/3864756
- 浅析C++中虚函数的调用及对象的内部布局http://blog.csdn.net/starlee/article/details/2089358
- 线程同步(同步对象、同步访问对象)http://blog.csdn.net/akof1314/article/details/5764200
- WinRAR命令行参数 转自:http://blog.csdn.net/cjolj/article/details/1592529
- H264参数语法文档: SPS、PPS、IDR( http://blog.csdn.net/heanyu/article/details/6205390)
- http://blog.csdn.net/jrq/article/details/4211075(URL参数中文乱码)
- apache 参数说明 转载自http://blog.csdn.net/Zhao1234567890123456/article/details/38569139
- 对select()参数fdset的完整理解 http://blog.csdn.net/maray/article/details/8285775
- tcpdump参数解析及使用详解(http://blog.csdn.net/hzhsan/article/details/43445787)
- Mongodb参数详解(参考:http://blog.csdn.net/freebird_lb/article/details/8229567)
- 函数指针与指针函数 http://blog.csdn.net/htyurencaotang/article/details/11490081
- C/C++ 开发库 | C/C++ Development Library http://blog.csdn.net/herorenme/article/details/18795935
- 4-进程
- 自控行业的PID算法分类详解
- 【计算机视觉】期刊整理
- Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
- 客户端提交emoji到服务端,服务端出错的处理方式[转]
- C++对象作为函数参数 http://blog.csdn.net/tms_li/article/details/7765626
- jvm问题及思考
- Nginx服务器的安装
- 精确到秒的JQuery日期控件,jquery日历插件,jquery日期插件
- 57-题目1441:人见人爱 A ^ B
- 面向对象编程中引用和const的结合
- javascript验证用户登录信息
- No configuration found for the specified action: '' in namespace: ''. Form action defaulting to 'act
- ICloneable接口