Recently the company recruit more, thus interviewed a lot of C + + programmers. During the interview, I would ask questions about parameter passing, with particular emphasis on pointers. Because pointers are, after all, one of the most important advantages of C + + ( and in some cases, a disadvantage ). But the result is that1/3 people are basically wrong,1/3 know it but do not know why. So I think it is necessary to put these knowledge points under the comb, share. ( The following discussion is based on The default compilation method for VS and GCC, and other special compilations are not within the scope of this article.) )
There are three kinds of methods for passing the function parameters: value passing (pass by value), pointer passing (pass Bypointer), reference passing (pass by reference).
the pass-through channel of the C + + function parameter is passed through the stack, by default follows __cdecl (C declaration ), the parameters are pressed from right to left by the caller, and the stack is restored by the caller after the function call is complete. (Win32API Follow the stdcall parameter Specification , not in the scope of this article )
Here is the test code
voidSwap (__int64* _pnx, __int64*_pny) {__int64 ntemp= *_pnx; *_PNX = *_pny; *_PNY =ntemp;}voidSwap (__int64& _nx, __int64&_ny) {__int64 ntemp=_nx; _nx=_ny; _ny=ntemp;}voidSetValue (__int64 _nx) {__int64 ntemp=_nx;}//Test001voidGetMemory (__int64*_pbuff) {_pbuff=New__int64[4];}//Test002voidGetMemory (__int64**_ppbuff) { *_ppbuff =New__int64[4];}int_tmain (intARGC, _tchar*argv[]) {__int64 NA=0x10; __int64 NB=0x20; //Test to pass by PointerSwap (&na, &NB); //Test to pass by referenceSwap (NA, NB); //Test to pass by valueSetValue (NA); //Test The pointer that points the pointer__int64* _parray =NULL; GetMemory (&_parray); Delete[] _parray; _parray=NULL; //Test the pointergetmemory (_parray); return 0;}
Pointer passing and reference passing
//Here's a look at the corresponding disassembly code (VS version)__int64 NA =0x10; 0041370E mov dword ptr [na],10h00413715mov DWORD ptr [ebp-8],0__int64 NB=0x20; 0041371C mov dword ptr [nb],20h00413723mov dword ptr [ebp-18h],0 //Test to pass by PointerSwap (&na, &NB) 0041372A Lea EAX,[NB] 0041372D push eax 0041372E Lea Ecx,[na]00413731push ECX00413732Call Swap (4111e5h)00413737Add ESP,8 //Test to pass by referenceSwap (NA, NB), 0041373A Lea EAX,[NB] 0041373D push eax 0041373E Lea Ecx,[na]00413741push ECX00413742Call Swap (4111e0h)00413747Add ESP,8 //gcc version 0x00401582<+ -: Lea eax,[esp+0x18] 0x00401586<+ the: mov DWORD PTR [esp+0x4],eax0x0040158a<+ -: Lea eax,[esp+0x1c] 0x0040158e<+ the>: mov DWORD PTR [esp],eax0x00401591<+ $: Call0x401520<swap (int*,int*) >0x00401596<+ -: Lea eax,[esp+0x18] 0x0040159a<+ Wu: mov DWORD PTR [esp+0x4],eax0x0040159e<+ -: Lea eax,[esp+0x1c] 0X004015A2<+ +>: mov DWORD PTR [esp],eax0x004015a5<+ $: Call0x401542<swap (int&,int&) >
with the disassembly code above, we can see that pointer passing and reference passing are the same in the mechanism, that is, the pointer value (that is, the address ) is pressed into the stack, the function is called, and then the stack is restored. swap (NA, NB) and swap (&na, &NB); In fact, the assembly code is basically exactly the same, all from the stack to remove the address. From this you can see that the reference and pointer are the same in efficiency. This is why both pointers and references can achieve polymorphic effects. Pointer passing and reference passing are actually changing the value of the address point to the memory to achieve the effect of modifying the parameters.
Value passing
The following is the disassembly code for the value passing corresponding
Test to pass by Valuesetvalue (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
because my machine is a CPU, the assembly code from the above can see that the 64Bit variable is divided into 2 32Bit parameters pressed into the stack. This is what we often say, value passing will form a copy. If it is a custom structure type, and there are many parameters, then if the value is passed, the structure will be divided into a very large number of 32Bit copies to the stack, so that the parameter transfer efficiency is very slow. So a struct, such as custom types, are passed by reference, and if you do not want others to modify struct variables, you can add a const modifier, such as (const my_struct& _value);
Here 's a look at the parameter passing of the disassembly code corresponding to the TEST001 function
__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
As can be seen from the assembly code above, in fact, 0 is pressed into the stack as a parameter, so getmemory (_parray) regardless of what to do, in fact, is not related to pointer variable _parray . getmemory () allocated space is to let the temporary variables in the stack point to, when the function exits, the stack is restored, the result of the application of space without a person in the tube, resulting in a memory leak problem. TheC + + Primer theparameter passing into both reference and non-reference passing, and non-reference passing can actually be interpreted as a value pass. Thus, pointer passing is also a value pass in a sense, because the value of the pointer is passed (1 4BYTE values ). Value passing does not change the value of the passed-in argument. And the normal pointer pass is actually the content that changes the pointer variable to point to.
Let's take a look at the parameter passing of the disassembly code corresponding to the TEST002 function
__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
From the assembly code Lea Eax,[_parray] , it can be seen that_parray 's address is pressed into the stack.
Then take a look at the implementation assembly code for 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
The blue code allocates temporary variable space and then calls the allocation space function to allocate space , resulting in a spatial pointer that is eax.
The Red assembly code is then taken from the ebp+0x8 Stack to the address of the parameter _pArray that is pressed into the stack.
mov DWORD PTR [edx], eax is equivalent to assigning the space pointer eax let edx Point, also let _parray points to the allocated space eax.
In summary, regardless of which parameter is passed, the parameters are indirectly involved in the called function through temporary variables on the stack. As a parameter, the value of the pointer itself cannot be changed, and the content that can be changed is what it points to. References are implemented by pointers, so the references and pointers are the same in efficiency.
The parameter passing mechanism of C + +