C++对象作为函数参数
来源:互联网 发布:酒店数据库管理系统 编辑:程序博客网 时间:2024/05/16 01:12
关于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++】对象作为函数参数【原创技术】
- 对象作为函数参数
- 对象作为函数参数
- 【Objective-C】02-OC对象作为参数传递给函数
- C++对象作为函数参数
- c++对象作为函数参数
- 类对象作为函数参数
- 类对象作为函数参数
- C把函数作为参数
- CPen 对象不能作为函数的参数
- C#函数 把 对象作为参数传递
- 数组、对象分别作为函数参数时
- C++传递对象函数指针作为参数
- 类对象作为函数参数传递
- Python之函数对象作为参数
- R语言-引用函数对象作为参数
- Objective-C - 对象作为方法的参数
- C++.net 定义类 将类对象作为函数参数传入另一个类 出现错误
- Makefile条件判断 ——————————【Badboy】
- 【unity3d Editor开发】简单节点编辑器(一)
- Android中如何做到Service被关闭后又自动启动
- 插入排序
- qsort对动态二维数组进行排序
- C++对象作为函数参数
- C指针操作——获取字符串中某个特定的字符
- Cocos2d-js官方完整项目教程翻译:八、跟我们的游戏添加游戏币和障碍物
- 『ANDROID』Android实现图片缩放与旋转
- 内存管理
- 【 D3.js 入门系列 --- 9.6 】 打包图的制作
- zoj 1014
- Read_Text函数的使用方法
- swift笔记1