四网合一网站建设,呼和浩特网站开发 千投,西安建设科技专修学院官方网站,网站域名去哪里备案目录 1.   主要区别 
2.   例释(以Windows X64平台为例) 1.   主要区别 在函数传参中#xff0c;传引用在本质上就是传地址#xff0c;而传值调用是利用函数的栈空间进行传递#xff0c;先将实体复制一份到栈内存#xff0c;再通过内存栈传递参数。同时#xff0c;通过传引…目录 1.   主要区别 
2.   例释(以Windows X64平台为例) 1.   主要区别 在函数传参中传引用在本质上就是传地址而传值调用是利用函数的栈空间进行传递先将实体复制一份到栈内存再通过内存栈传递参数。同时通过传引用和传地址的任何对象如果改动了任何属性是直接改动原对象而传值只会改变副本不会改变原对象。 
2.   例释(以Windows X64平台为例) 为了简单起见定义一个结构体 
struct DataEntity 
{ __int64 m  0x1111111111111111; //为了便于观察内存每一个字节都赋值 __int64 n  0x2222222222222222; __int64 Add() { return m  n; } 
}; 
定义三个函数分别按传地址传引用传值方式传参 
void PrintPassByReference(DataEntity data) 
{ __int64 total  data.m  data.n; 
} void PrintPassByPtr(DataEntity* data) 
{ __int64 total  data-m  data-n; 
} void PrintPassByValue(DataEntity data) 
{ __int64 total  data.m  data.n; 
} 
调用代码 DataEntity data; PrintPassByReference(data); PrintPassByPtr(data); PrintPassByValue(data); 
汇编代码分析 DataEntity data; 
00007FF658FD50A3  lea         rcx,[data]   
00007FF658FD50A8  call        DataEntity::DataEntity (07FF658E56F55h)   PrintPassByReference(data); 
00007FF658FD50AD  lea         rcx,[data]  ; 将 data 的地址存入寄存器rcx 
00007FF658FD50B2  call        PrintPassByReference (07FF658E56F5Ah)   
进入 PrintPassByReference 
void PrintPassByReference(DataEntity data) 
{ 
00007FF658FD4FE0  mov         qword ptr [rsp8],rcx  取出data的地址 
00007FF658FD4FE5  sub         rsp,18h   __int64 total  data.m  data.n; 
00007FF658FD4FE9  mov         rax,qword ptr [data]  ;将data首地址送入rax 
00007FF658FD4FEE  mov         rax,qword ptr [rax]   
00007FF658FD4FF1  mov         rcx,qword ptr [data]   
00007FF658FD4FF6  add         rax,qword ptr [rcx8]   
00007FF658FD4FFA  mov         qword ptr [rsp],rax   
} 
00007FF658FD4FFE  add         rsp,18h   
00007FF658FD5002  ret   PrintPassByPtr(data); 
00007FF658FD50B7  lea         rcx,[data]  将 data 的地址存入寄存器 rcx 
00007FF658FD50BC  call        PrintPassByPtr (07FF658E56F69h)   
;可以看出在调用方式上与 PrintPassByReference 相同。 
进入 PrintPassByPtr(data); 
void PrintPassByPtr(DataEntity* data) 
{ 
00007FF658FD5010  mov         qword ptr [rsp8],rcx  ;取出data的地址 
00007FF658FD5015  sub         rsp,18h   __int64 total  data-m  data-n; 
00007FF658FD5019  mov         rax,qword ptr [data]   
00007FF658FD501E  mov         rax,qword ptr [rax]   
00007FF658FD5021  mov         rcx,qword ptr [data]   
00007FF658FD5026  add         rax,qword ptr [rcx8]   
00007FF658FD502A  mov         qword ptr [rsp],rax   
} 
00007FF658FD502E  add         rsp,18h   
00007FF658FD5032  ret 
从以上可以看出PrintPassByReference 和 PrintPassByPtr 生成的汇编代码基本一致二者都是直接传递数据的地址。 
现在看看在进入PrintPassByValue之前的准备 PrintPassByValue(data); 
00007FF658FD50C1  lea         rax,[rsp40h]  ;分配 40h 的栈空间 
00007FF658FD50C6  lea         rcx,[data]  ;取得 data 的地址 
00007FF658FD50CB  mov         rdi,rax  ;  分配的空间地址送入寄存器rdi 
00007FF658FD50CE  mov         rsi,rcx  ; data 送入寄存器 rsi 
00007FF658FD50D1  mov         ecx,10h  计数器值赋为 16 (data大小为16字节) 
00007FF658FD50D6  rep movs    byte ptr [rdi],byte ptr [rsi]  按字节复制data到新的空间 
00007FF658FD50D8  lea         rcx,[rsp40h]  将栈空间地址送入rcx 
00007FF658FD50DD  call        PrintPassByValue (07FF658E56F5Fh)   
说明以上红色部分为新分配栈空间并复制对象副本这个过程对于 C 程序员是隐藏的。 
进入 PrintPassByValue 
void PrintPassByValue(DataEntity data) 
{ 
00007FF66BA05040  mov         qword ptr [rsp8],rcx  取出栈中存储的data副本 
00007FF66BA05045  sub         rsp,18h   __int64 total  data.m  data.n; 
00007FF66BA05049  mov         rax,qword ptr [data]  这个data是栈中存储的副本 
00007FF66BA0504E  mov         rax,qword ptr [rax]   
00007FF66BA05051  mov         rcx,qword ptr [data]   
00007FF66BA05056  add         rax,qword ptr [rcx8]   
00007FF66BA0505A  mov         qword ptr [rsp],rax   
} 
00007FF66BA0505E  add         rsp,18h   
00007FF66BA05062  ret   
传值是对副本对应的内存进行操作当然不会改变原对象。