recently the company recruit more, thus interviewed a lot ofC + +programmer. During the interview, I would ask questions about parameter passing, with particular emphasis on pointers. Because the pointer is after allC + +one of the most important advantages(in some cases it could be a disadvantage.). But the result is that1/3people are basically wrong about that1/3but I do not know the reason why. So I think it is necessary to put these knowledge points under the comb, share. (The following discussion is based onVSand theGCCthe default compilation method, other special compilation methods are not within the scope of this article. )
C + + There are three ways to pass function parameters: value passing (pass by value), pointer passing (pass Bypointer), reference passing (pass by reference).
C + + The pass channel of the function parameter is passed through the stack, which is followed by default __cdecl (C declaration method ) , the parameters are pressed by the caller from right to left, 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
void Swap (__int64* _pnx, __int64* _pny) {__int64 ntemp = *_pnx;*_pnx = *_pny;*_pny = ntemp;} void Swap (__int64& _nx, __int64& _ny) {__int64 ntemp = _nx;_nx = _ny;_ny = ntemp;} void SetValue (__int64 _nx) {__int64 ntemp = _nx;} Test001void getmemory (__int64* _pbuff) {_pbuff = new __int64[4];} Test002void getmemory (__int64** _ppbuff) {*_ppbuff = new __int64[4];} int _tmain (int argc, _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);d elete[] _parray;_parray = null;//Test The pointer getmemory (_parray); return 0;}
Pointer passing and reference passing
__int64 NA = 0x10;0041370e mov dword ptr [na],10h 00413715 mov dword ptr [ebp-8],0 __int64 NB = 0x20;004 1371C mov dword ptr [nb],20h 00413723 mov dword ptr [ebp-18h],0//Test to pass by Pointerswap (&na, &NB) 0041372A Lea EAX,[NB] 0041372D push eax 0041372E Lea Ecx,[na] 00413731 push EC X 00413732 call Swap (4111e5h) 00413737 add esp,8 <span style= "font-weight:bold;" ></span>//Test to pass by Referenceswap (NA, NB), 0041373A Lea EAX,[NB] 0041373D push eax 004137 3E Lea Ecx,[na] 00413741 push ecx 00413742 call Swap (4111e0h) 00413747 add esp,8//GC Version C 0x00401582 <+30>:lea eax,[esp+0x18] 0x00401586 <+34>:mov DWORD PTR [esp+0x4],eax 0x0040158a < ; +38>:lea eax,[esp+0x1c] 0x0040158e <+42>:mov DWORD PTR [esp],eax 0x00401591 <+45>:call 0x40152 0 <swap (int*, int*) > 0x00401596<+50>:lea eax,[esp+0x18] 0x0040159a <+54>:mov DWORD PTR [esp+0x4],eax 0x0040159e <+58>:lea EAX,[ESP+0X1C] 0X004015A2 <+62>:mov DWORD PTR [esp],eax 0x004015a5 <+65>:call 0x401542 <Swap (INT&A MP;, int&) ><span style= "Font-weight:bold;" ></span>
with the disassembly code above, we can see that pointer passing and reference passing are the same as the mechanism, all of which are pointer values ( i.e. address ) press into the stack, call the function, and then restore the stack.
Swap (NA,NB) and the 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 32 bit cpu, from the assembly code above can see 64bit variables are divided into 2 32bit parameters are 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. Therefore, the structure of the custom types, all use reference passing, if you do not want others to modify the structure of variables, you can add a const modifier, such as (constmy_struct& _value);
here 's a look. Test001 parameter passing of the disassembly code corresponding to the 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
from the above assembly code can be seen, in fact, is0is pressed into the stack as a parameter, sogetmemory (_parray)no matter what you do, actually all with pointer variables_parrayirrelevant. getmemory ()The 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 tube, resulting in a memory leak problem. TheC + + Primerthe arguments are passed into both reference and non-reference passes, and non-reference passes can actually be interpreted as value passing. Thus, pointer passing is also a value pass in a sense, because the value of the pointer is passed(1a4BYTEthe value). 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 . Test002 parameter passing of the disassembly code corresponding to the 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
from the assembly code above Lea Eax,[_parray] As you can see,_parray 's address is pushed into the stack.
and take a look at it. getmemory (&_parray Implementation assembly code.
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 the temporary variable space and then calls the allocation space function to allocate space , The resulting space pointer is eax .
then red assembly code from ebp+0x8 The stack on the top of the stack to take the parameters _p The address of the array
mov DWORD PTR [edx],eax which is equivalent to assigning a space pointer eax Let edx point, that is, let _parray point to 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 + +