【C++学习】C++中按引用传递与按值传递的具体原理

C++中按引用传递与按值传递的具体原理

一、测试代码

cpp 复制代码
void Test(int& a) 
{
	a = 10;
}

void TestA(int a) {
	a = 5;
}


int main()
{

	int a = 10;
	int* b = &a;
	int& c = a;

	a = 5;

	Test(a);

	TestA(a);

	*b = 3;
	c = 6;
	std::cout << a << std::endl;

	std::cin.get();
}

二、分析参数传递的区别

1.调用处反汇编

csharp 复制代码
	Test(a);
00007FF7549F1FDB  lea         rcx,[a]  
00007FF7549F1FDF  call        Test (07FF7549F1465h)  

	TestA(a);
00007FF7549F1FE4  mov         ecx,dword ptr [a]  
00007FF7549F1FE7  call        TestA (07FF7549F146Ah)  

解读:可以看到按引用传递的话,是用lea指令将变量a的地址,放到rcx寄存器中,按值传递用mov指令,将变量a地址所在的值,放到ecx寄存器重。

2.被调用处反汇编

1.Test引用传递方式汇编代码如下(示例):

c 复制代码
void Test(int& a) 
{
00007FF7549F1960  mov         qword ptr [rsp+8],rcx  
00007FF7549F1965  push        rbp  
00007FF7549F1966  push        rdi  
00007FF7549F1967  sub         rsp,0E8h  
00007FF7549F196E  lea         rbp,[rsp+20h]  
00007FF7549F1973  lea         rcx,[__AEDBAAFC_Math@cpp (07FF754A03067h)]  
00007FF7549F197A  call        __CheckForDebuggerJustMyCode (07FF7549F13FCh)  
	a = 10;
00007FF7549F197F  mov         rax,qword ptr [a]  
00007FF7549F1986  mov         dword ptr [rax],0Ah  

可以看到**mov qword ptr [rsp+8],rcx **将rcx的值(调用处main函数中变量a的地址)放到rsp+8表示的地址内(即Test函数中的本地变量a中),此时本地变量Test函数a中的值,其实是一个地址(指向main函数中的变量a的地址)。后续a = 10的汇编,可以看到是由两条指令完成:
mov rax,qword ptr [a]
mov dword ptr [rax],0Ah

可以看到完全将对本地变量a的操作当成指针来操作了,先取a地址内的值(main函数中a地址)复制到rax寄存器中,然后将0Ah(数值10)复制到rax值表示的地址(即main函数a地址)中。

2.TestA函数按值传递汇编如下:

cpp 复制代码
00007FF7549F1A10  mov         dword ptr [rsp+8],ecx  
00007FF7549F1A14  push        rbp  
00007FF7549F1A15  push        rdi  
00007FF7549F1A16  sub         rsp,0E8h  
00007FF7549F1A1D  lea         rbp,[rsp+20h]  
00007FF7549F1A22  lea         rcx,[__AEDBAAFC_Math@cpp (07FF754A03067h)]  
00007FF7549F1A29  call        __CheckForDebuggerJustMyCode (07FF7549F13FCh)  
	a = 5;
00007FF7549F1A2E  mov         dword ptr [a],5 

同样的,mov dword ptr [rsp+8],ecx 可以看到将ecx寄存器中值放到rsp+8表示的地址内(即TestA函数中的本地变量a中)

最后a =10;的汇编与上面完全不同,只有一条mov指令,将数值5直接复制到本地变量a表示的地址。

总结

可以看出C++中按引用传递,与按值传递,编译器给生成两种不同的指令。按引用传递,传递的是变量的地址,有点类似指针传递(但是指针传递,需要新建指针变量,以按值的方式传递指针值,相当于间接引用),按引用传递比按指针传递更加简化了。

最后可以看看,引用变量相关的汇编,也可以看出引用其实内部都是按地址处理的。

cpp 复制代码
	int* b = &a;
00007FF7549F1FC4  lea         rax,[a]  
00007FF7549F1FC8  mov         qword ptr [b],rax  
	int& c = a;
00007FF7549F1FCC  lea         rax,[a]  
00007FF7549F1FD0  mov         qword ptr [c],rax  
cpp 复制代码
	*b = 3;
00007FF7549F1FEC  mov         rax,qword ptr [b]  
00007FF7549F1FF0  mov         dword ptr [rax],3  
	c = 6;
00007FF7549F1FF6  mov         rax,qword ptr [c]  
00007FF7549F1FFA  mov         dword ptr [rax],6 
相关推荐
AlexMercer1012几秒前
【C++】二、数据类型 (同C)
c语言·开发语言·数据结构·c++·笔记·算法
friklogff2 分钟前
【无标题】云端之C#:全面解析6种云服务提供商的SDK
开发语言·flask·c#
dot.Net安全矩阵9 分钟前
.NET内网实战:通过命令行解密Web.config
前端·学习·安全·web安全·矩阵·.net
Reese_Cool15 分钟前
【C语言二级考试】循环结构设计
android·java·c语言·开发语言
海里真的有鱼16 分钟前
Spring Boot 项目中整合 RabbitMQ,使用死信队列(Dead Letter Exchange, DLX)实现延迟队列功能
开发语言·后端·rabbitmq
zxctsclrjjjcph32 分钟前
【C语言】常见的C语言概念
c语言·开发语言
小灰灰爱代码37 分钟前
C++——求3个数中最大的数(分别考虑整数、双精度数、长整数的情况),用函数模板来实现。
开发语言·c++·算法
微刻时光40 分钟前
Redis集群知识及实战
数据库·redis·笔记·学习·程序人生·缓存
Eiceblue44 分钟前
Python 复制Excel 中的行、列、单元格
开发语言·python·excel
项目題供诗1 小时前
尚品汇-秒杀商品存入缓存、Redis发布订阅实现状态位(五十一)
开发语言·php