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的首地址)。
      具体分析过程,见代码注释。

点击(此处)折叠或打开

  1. //C++源码。
  2. //VC6.0

  3. #include<iostream>
  4. #include<cstdio>
  5. using namespace std;

  6. class CBase{
  7.  int i;
  8. public:
  9.  CBase(int i=0)
  10.  {
  11.   this->i=i;
  12.  }
  13.  CBase(CBase& rhs)//拷贝构造函数。
  14.  {
  15.   i=rhs.i;
  16.   printf("拷贝构造函数=%d\n",i);
  17.  }
  18.  void show(CBase B1, CBase B2)//对象作为形参。
  19.  {
  20.   printf("show=%d,%d\n",B1.i,B2.i);
  21.  }
  22. };
  23. int main()
  24. {
  25.  CBase Base;
  26.  CBase Basex(1);
  27.  CBase Basexx(2);

  28.  Base.show(Basex,Basexx);
  29. // printf("this is an end!\n");
  30. }
  31. ---------------------------------------------------------------------------------
  32. //main函数对应的汇编代码。
  33.  int main()
  34. 24: {
  35. 0040D4A0 push ebp
  36. 0040D4A1 mov ebp,esp
  37. 0040D4A3 sub esp,54h
  38. 0040D4A6 push ebx
  39. 0040D4A7 push esi
  40. 0040D4A8 push edi
  41. 0040D4A9 lea edi,[ebp-54h]
  42. 0040D4AC mov ecx,15h
  43. 0040D4B1 mov eax,0CCCCCCCCh
  44. 0040D4B6 rep stos dword ptr [edi]
  45. 25: CBase Base;
  46. 0040D4B8 push 0
  47. 0040D4BA lea ecx,[ebp-4]//ecx保存的是对象Base的this指针。
  48. 0040D4BD call @ILT+0(CBase::CBase)(00401005)//调用构造函数
  49. 26: CBase Basex(1);
  50. 0040D4C2 push 1
  51. 0040D4C4 lea ecx,[ebp-8]//ecx保存的是对象Basex的this指针。
  52. 0040D4C7 call @ILT+0(CBase::CBase)(00401005)//调用构造函数
  53. 27: CBase Basexx(2);
  54. 0040D4CC push 2
  55. 0040D4CE lea ecx,[ebp-0Ch]//ecx保存的是对象Basexx的this指针。
  56. 0040D4D1 call @ILT+0(CBase::CBase)(00401005)//调用构造函数

  57. 28: Base.show(Basex,Basexx);
  58. 0040D4D6 push ecx //等价于esp=esp-4;
  59. 0040D4D7 mov ecx,esp //ecx保存的是show函数的形参B2的this指针。
  60. 0040D4D9 lea eax,[ebp-0Ch]
  61. 0040D4DC push eax //对Basexx的this(即Basexx对象的首地址)指针压栈。
  62. 0040D4DD call @ILT+10(CBase::CBase)(0040100f)//调用拷贝构造函数
  63. 0040D4E2 push ecx //等价于esp=esp-4;
  64. 0040D4E3 mov ecx,esp //ecx保存的是show函数的形参B1的this指针。
  65. 0040D4E5 lea edx,[ebp-8]
  66. 0040D4E8 push edx //对Basex的this(即Basex对象的首地址)指针压栈。
  67. 0040D4E9 call @ILT+10(CBase::CBase)(0040100f)//调用拷贝构造函数
  68. 0040D4EE lea ecx,[ebp-4]//ecx保存的是Base对象的this指针。
  69. 0040D4F1 call @ILT+20(CBase::show)(00401019)//调用show函数。
  70. 29: printf("this is an end!\n");
  71. 0040D4F6 push offset string "this is an end!\n" (00422fa4)
  72. 0040D4FB call printf (0040d7c0)
  73. 0040D500 add esp,4
  74. 30: }
  75. 0040D503 pop edi
  76. 0040D504 pop esi
  77. 0040D505 pop ebx
  78. 0040D506 add esp,54h
  79. 0040D509 cmp ebp,esp
  80. 0040D50B call __chkesp (004010b0)
  81. 0040D510 mov esp,ebp
  82. 0040D512 pop ebp
  83. 0040D513 ret

  84. //show函数对应的汇编代码。
  85. 16: void show(CBase B1,CBase B2)
  86. 17: {
  87. 0040D550 push ebp
  88. 0040D551 mov ebp,esp
  89. 0040D553 sub esp,44h
  90. 0040D556 push ebx
  91. 0040D557 push esi
  92. 0040D558 push edi
  93. 0040D559 push ecx
  94. 0040D55A lea edi,[ebp-44h]
  95. 0040D55D mov ecx,11h
  96. 0040D562 mov eax,0CCCCCCCCh
  97. 0040D567 rep stos dword ptr [edi]
  98. 0040D569 pop ecx
  99. 0040D56A mov dword ptr [ebp-4],ecx
  100. 18: printf("show=%d,%d\n",B1.i,B2.i);
  101. 0040D56D mov eax,dword ptr [ebp+0Ch]//ebp+0Ch对应的是B2的首地址。
  102. 0040D570 push eax
  103. 0040D571 mov ecx,dword ptr [ebp+8]//ebp+8h对应的是B1的首地址。
  104. 0040D574 push ecx
  105. 0040D575 push offset string "show=%d,%d\n" (00422fcc)
  106. 0040D57A call printf (0040d7c0)
  107. 0040D57F add esp,0Ch
  108. 19: }
  109. 0040D582 pop edi
  110. 0040D583 pop esi
  111. 0040D584 pop ebx
  112. 0040D585 add esp,44h
  113. 0040D588 cmp ebp,esp
  114. 0040D58A call __chkesp (004010b0)
  115. 0040D58F mov esp,ebp
  116. 0040D591 pop ebp
  117. 0040D592 ret 8

  118. //拷贝构造函数对应的汇编代码(注释略)。
  119. 11: CBase(CBase& rhs)
  120. 0040D840 push ebp
  121. 0040D841 mov ebp,esp
  122. 0040D843 sub esp,44h
  123. 0040D846 push ebx
  124. 0040D847 push esi
  125. 0040D848 push edi
  126. 0040D849 push ecx
  127. 0040D84A lea edi,[ebp-44h]
  128. 0040D84D mov ecx,11h
  129. 0040D852 mov eax,0CCCCCCCCh
  130. 0040D857 rep stos dword ptr [edi]
  131. 0040D859 pop ecx
  132. 0040D85A mov dword ptr [ebp-4],ecx
  133. 12: {
  134. 13: i=rhs.i;
  135. 0040D85D mov eax,dword ptr [ebp-4]
  136. 0040D860 mov ecx,dword ptr [ebp+8]
  137. 0040D863 mov edx,dword ptr [ecx]
  138. 0040D865 mov dword ptr [eax],edx
  139. 14: printf("拷贝构造函数=%d\n",i);
  140. 0040D867 mov eax,dword ptr [ebp-4]
  141. 0040D86A mov ecx,dword ptr [eax]
  142. 0040D86C push ecx
  143. 0040D86D push offset string "\xbf\xbd\xb1\xb4\xb9\xb9\xd4\xec\xba\xaf\xca\xfd=%d\n" (00422fb8)
  144. 0040D872 call printf (0040d7c0)
  145. 0040D877 add esp,8
  146. 15: }
  147. 0040D87A mov eax,dword ptr [ebp-4]
  148. 0040D87D pop edi
  149. 0040D87E pop esi
  150. 0040D87F pop ebx
  151. 0040D880 add esp,44h
  152. 0040D883 cmp ebp,esp
  153. 0040D885 call __chkesp (004010b0)
  154. 0040D88A mov esp,ebp
  155. 0040D88C pop ebp
  156. 0040D88D ret 4

 当执行show函数作用域内代码时,栈结构图示如下:




0 0
原创粉丝点击