C/C++的参数传递机制
作者:网络转载 发布时间:[ 2015/1/19 13:13:33 ] 推荐标签:Net 软件开发
通过上面的反汇编代码,我们可以看出指针传递和引用传递在机制是一样的,都是将指针值(即地址)压入栈中,调用函数,然后恢复栈。Swap(nA, nB)和Swap(&nA, &nB);在实际上的汇编代码也基本上一模一样,都是从栈中取出地址来。由此可以看出引用和指针在效率上是一样的。这也是为什么指针和引用都可以达到多态的效果。指针传递和引用传递其实都是改变的地址指向的内存上的值来达到修改参数的效果。
值传递
下面是值传递对应的反汇编代码
// Test to pass by value
SetValue(nA);
0041374A mov eax,dword ptr [ebp-8]
0041374D push eax
0041374E mov ecx,dword ptr [nA]
00413751 push ecx
00413752 call SetValue (4111EAh)
00413757 add esp,8
因为我的机器是32位的CPU,从上面的汇编代码可以看64Bit的变量被分成2个32Bit的参数压入栈中。这也是我们常说的,值传递会形成一个拷贝。如果是一个自定义的结构类型,并且有很多参数,那么如果用值传递,这个结构体将被分割为非常多个32Bit的逐个拷贝到栈中去,这样的参数传递效率是非常慢的。所以结构体等自定义类型,都使用引用传递,如果不希望别人修改结构体变量,可以加上const修饰,如(const MY_STRUCT& _value);
下面来看一下Test001函数对应的反汇编代码的参数传递
__int64* _pArray = NULL;
004137E0 mov dword ptr [_pArray],0
// Test the pointer
GetMemory(_pArray);
00413812 mov eax,dword ptr [_pArray]
00413815 push eax
00413816 call GetMemory (411203h)
0041381B add esp,4
从上面的汇编代码可以看出,其实是0被压入到栈中作为参数,所以GetMemory(_pArray)无论做什么事,其实都与指针变量_pArray无关。GetMemory()分配的空间是让栈中的临时变量指向的,当函数退出时,栈得到恢复,结果申请的空间没有人管,产生内存泄露的问题了。《C++ Primer》将参数传递分为引用传递和非引用传递两种,非引用传递其实可以理解为值传递。这样看来,指针传递在某种意义上也是值传递,因为传递的是指针的值(1个4BYTE的值)。值传递都不会改变传入实参的值的。而且普通的指针传递其实是改变的指针变量指向的内容。
下面再看一下Test002函数对应的反汇编代码的参数传递
__int64* _pArray = NULL;
004137E0 mov dword ptr [_pArray],0
GetMemory(&_pArray);
004137E7 lea eax,[_pArray]
004137EA push eax
004137EB call GetMemory (4111FEh)
004137F0 add esp,4
从上面的汇编代码lea eax,[_pArray] 可以看出,_pArray的地址被压入到栈中去了。
然后看一看GetMemory(&_pArray)的实现汇编代码。
0x0040159b <+0>: push ebp
0x0040159c <+1>: mov ebp,esp
0x0040159e <+3>: sub esp,0x18
0x004015a1 <+6>: mov DWORD PTR [esp],0x20
0x004015a8 <+13>: call 0x473ef0 <_Znaj>
0x004015ad <+18>: mov edx,DWORD PTR [ebp+0x8]
0x004015b0 <+21>: mov DWORD PTR [edx],eax
0x004015b2 <+23>: leave
0x004015b3 <+24>: ret
蓝色的代码是分配临时变量空间,然后调用分配空间函数分配空间,得到的空间指针即eax.
然后红色的汇编代码即从ebp+0x8的栈上取到上面压入栈中的参数_pArray的地址.
mov DWORD PTR [edx],eax即相当于把分配的空间指针eax让edx指向,也即让_pArray指向分配的空间eax.
总之,无论是哪种参数传递方式,参数都是通过栈上的临时变量来间接参与到被调用函数的。指针作为参数,其本身的值是不可能被改变的,能够改变的是其指向的内容。引用是通过指针来实现的,所以引用和指针在效率上一样的。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11