C++ 学习之旅(8)——一文搞懂指针、引用、函数参数的传值调用、指针调用和引用调用

废话少说,直接上代码:

#include <iostream>

int  main()
{
	int a = 5;
	int* ptr = &a;
	int& ref = a;
	std::cin.get(); //设置断点
}

为了避免混淆,我建议在定义指针时写int* ptr而不是int *ptr,同理,定义引用写成int& ref而不是int &ref

设置断点,然后Debug程序,看看源程序的汇编程序是什么:
在这里插入图片描述
在这里插入图片描述
精彩的地方来了,指针和引用实际上干的是同样的事,都是把变量a所在的偏移地址传给ptr指针,只不过指针的标号名为ptr,引用的标号名为ref而已。

再看看赋值操作:

#include <iostream>

int  main()
{
	int a = 5;
	int* ptr = &a;
	int& ref = a;
	*ptr = 6; //赋值
	ref = 7;  //赋值
	std::cin.get();
}

在这里插入图片描述
在汇编语言中还是一样的!

最后看一下函数参数传递的三种方式:

#include <iostream>

void Increment1(int value) //传值
{
	value++;
}

void Increment2(int* value) //指针
{
	(*value)++;
}

void Increment3(int& value) //引用
{
	value++;
}

int  main()
{
	int a = 5;
	Increment1(a);
	Increment2(&a);
	Increment3(a);
	std::cin.get();
}

Increment1函数

在这里插入图片描述
Increment2函数

在这里插入图片描述

Increment3函数

在这里插入图片描述
可以看到指针和引用还是一样的,结合调用的代码看:

在这里插入图片描述
首先,把5送到内存地址为a的双字大小的空间中;
对于Increment1,从内存地址为a的双字大小的空间中取出内容(整数5),送到eax寄存器中,然后call函数Increment1,把eax加一,最后送到内存地址为value的空间中,而不是内存地址为a的空间,如图:
在这里插入图片描述
对于Increment2,取内存地址为a的偏移地址,送到eax寄存器中,然后call函数Increment2,如图:
在这里插入图片描述
先是寻址参数value,从中取出偏移地址送到eax,再用eax寻址,找到数值5送到ecx,然后ecx加一,再将结果ecx送回到偏移地址为value空间中记录的那个地址,即内存地址a,这样就实现了对a的加一操作。
在这里插入图片描述
顺便看下此时的value空间,记录的是内存地址a的偏移地址:

在这里插入图片描述
也就是说,如果使用传值调用,内存地址为参数value的空间中记录的就是数值,运算的结果也会记录在这里,但是如果函数退出,这一块空间就会清除,所以结果并没有保存。如果使用指针和引用调用,内存地址为参数value的空间中记录的就是偏移地址,然后根据这个偏移地址取值,作运算,结果也是根据这个偏移地址送回去,而这块空间即使函数退出也不会消失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值