Cpp指针和引用的区别

指针

#include <iostream>

using namespace std;

int * mac()
{
	int *i=new int(10);
	return i;
}

int macp(int *n)
{
	cout<<*n<<endl;
}
int main()
{
	int i=10;
	int *p=&i;
	int *pp=mac();
	printf("%d\n",*p);
	printf("%d\n",*pp);

	return 0;
}
汇编代码
   0x00005555555549e4 <+0>:	push   rbp
   0x00005555555549e5 <+1>:	mov    rbp,rsp
   0x00005555555549e8 <+4>:	sub    rsp,0x20
   0x00005555555549ec <+8>:	mov    rax,QWORD PTR fs:0x28
   0x00005555555549f5 <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x00005555555549f9 <+21>:	xor    eax,eax
   0x00005555555549fb <+23>:	mov    DWORD PTR [rbp-0x1c],0xa
=> 0x0000555555554a02 <+30>:	lea    rax,[rbp-0x1c]
   0x0000555555554a06 <+34>:	mov    QWORD PTR [rbp-0x18],rax
   0x0000555555554a0a <+38>:	call   0x55555555498a <mac()>
   0x0000555555554a0f <+43>:	mov    QWORD PTR [rbp-0x10],rax
   0x0000555555554a13 <+47>:	mov    rax,QWORD PTR [rbp-0x18]
   0x0000555555554a17 <+51>:	mov    eax,DWORD PTR [rax]
   0x0000555555554a19 <+53>:	mov    esi,eax
   0x0000555555554a1b <+55>:	lea    rdi,[rip+0x123]        # 0x555555554b45
   0x0000555555554a22 <+62>:	mov    eax,0x0
   0x0000555555554a27 <+67>:	call   0x555555554800 <printf@plt>
   0x0000555555554a2c <+72>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555554a30 <+76>:	mov    eax,DWORD PTR [rax]
   0x0000555555554a32 <+78>:	mov    esi,eax
   0x0000555555554a34 <+80>:	lea    rdi,[rip+0x10a]        # 0x555555554b45
   0x0000555555554a3b <+87>:	mov    eax,0x0
   0x0000555555554a40 <+92>:	call   0x555555554800 <printf@plt>
   0x0000555555554a45 <+97>:	mov    eax,0x0
   0x0000555555554a4a <+102>:	mov    rdx,QWORD PTR [rbp-0x8]
   0x0000555555554a4e <+106>:	xor    rdx,QWORD PTR fs:0x28
   0x0000555555554a57 <+115>:	je     0x555555554a5e <main()+122>
   0x0000555555554a59 <+117>:	call   0x555555554840 <__stack_chk_fail@plt>
   0x0000555555554a5e <+122>:	leave  
   0x0000555555554a5f <+123>:	ret    
End of assembler dump.
指针赋值
int *p=&i;
   0x0000555555554a02 <+30>:	lea    rax,[rbp-0x1c]
   0x0000555555554a06 <+34>:	mov    QWORD PTR [rbp-0x18],rax
   [rbp-0x1c]为i的首地址,lea指令取其地址而后放入rax中
   [rbp-0x18]为指针p的首地址,将rax中的值复制到其中完成指针的赋值
函数返回值
mac函数汇编代码
Dump of assembler code for function mac():
=> 0x000055555555498a <+0>:	push   rbp
   0x000055555555498b <+1>:	mov    rbp,rsp
   0x000055555555498e <+4>:	sub    rsp,0x10
   0x0000555555554992 <+8>:	mov    edi,0x4
   0x0000555555554997 <+13>:	call   0x555555554820 <_Znwm@plt>
   0x000055555555499c <+18>:	mov    DWORD PTR [rax],0xa
   0x00005555555549a2 <+24>:	mov    QWORD PTR [rbp-0x8],rax
   0x00005555555549a6 <+28>:	mov    rax,QWORD PTR [rbp-0x8]
   0x00005555555549aa <+32>:	leave  
   0x00005555555549ab <+33>:	ret    
End of assembler dump.

mov    rax,QWORD PTR [rbp-0x8] 将返回值存入rax寄存器中
mov    QWORD PTR [rbp-0x10],rax 将返回值复制到指针pp中
函数参数
   0x0000555555554a13 <+47>:	mov    rax,QWORD PTR [rbp-0x18]//将指针中保存的地址放入rax中
   0x0000555555554a17 <+51>:	mov    eax,DWORD PTR [rax]//取出值
   0x0000555555554a19 <+53>:	mov    esi,eax//利用地址取出值,该参数传递方法为寄存器传递
   0x0000555555554a1b <+55>:	lea    rdi,[rip+0x123]        # 0x555555554b45
   0x0000555555554a22 <+62>:	mov    eax,0x0
   0x0000555555554a27 <+67>:	call   0x555555554800 <printf@plt>

引用

#include <iostream>

using namespace std;

int&  mac()
{
	int *i=new int(10);
	return *i;
}

int macp(int &n)
{
	cout<<n<<endl;
}
int main()
{
	int i= 10;
	int &p=i;
	p=mac();
	macp(p);
	printf("%d\n",p);
	return 0;
}
汇编代码
(gdb) disassemble 
Dump of assembler code for function main():
   0x00005555555549e4 <+0>:	push   rbp
   0x00005555555549e5 <+1>:	mov    rbp,rsp
   0x00005555555549e8 <+4>:	sub    rsp,0x20
   0x00005555555549ec <+8>:	mov    rax,QWORD PTR fs:0x28
   0x00005555555549f5 <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x00005555555549f9 <+21>:	xor    eax,eax
=> 0x00005555555549fb <+23>:	mov    DWORD PTR [rbp-0x14],0xa
   0x0000555555554a02 <+30>:	lea    rax,[rbp-0x14]
   0x0000555555554a06 <+34>:	mov    QWORD PTR [rbp-0x10],rax
   0x0000555555554a0a <+38>:	call   0x55555555498a <mac()>
   0x0000555555554a0f <+43>:	mov    edx,DWORD PTR [rax]
   0x0000555555554a11 <+45>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555554a15 <+49>:	mov    DWORD PTR [rax],edx
   0x0000555555554a17 <+51>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555554a1b <+55>:	mov    rdi,rax
   0x0000555555554a1e <+58>:	call   0x5555555549ac <macp(int&)>
   0x0000555555554a23 <+63>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555554a27 <+67>:	mov    eax,DWORD PTR [rax]
   0x0000555555554a29 <+69>:	mov    esi,eax
   0x0000555555554a2b <+71>:	lea    rdi,[rip+0x113]        # 0x555555554b45
   0x0000555555554a32 <+78>:	mov    eax,0x0
   0x0000555555554a37 <+83>:	call   0x555555554800 <printf@plt>
   0x0000555555554a3c <+88>:	mov    eax,0x0
   0x0000555555554a41 <+93>:	mov    rcx,QWORD PTR [rbp-0x8]
   0x0000555555554a45 <+97>:	xor    rcx,QWORD PTR fs:0x28
   0x0000555555554a4e <+106>:	je     0x555555554a55 <main()+113>
   0x0000555555554a50 <+108>:	call   0x555555554840 <__stack_chk_fail@plt>
   0x0000555555554a55 <+113>:	leave  
   0x0000555555554a56 <+114>:	ret    
End of assembler dump.
引用初始化赋值
   0x0000555555554a02 <+30>:	lea    rax,[rbp-0x14]
   0x0000555555554a06 <+34>:	mov    QWORD PTR [rbp-0x10],rax
   对比指针赋值可以看出引用的赋值和指针的赋值是相同的方法
函数返回值
   mac函数汇编
   Dump of assembler code for function mac():
   0x000055555555498a <+0>:	push   rbp
   0x000055555555498b <+1>:	mov    rbp,rsp
   0x000055555555498e <+4>:	sub    rsp,0x10
   0x0000555555554992 <+8>:	mov    edi,0x4
   0x0000555555554997 <+13>:	call   0x555555554820 <_Znwm@plt>
   0x000055555555499c <+18>:	mov    DWORD PTR [rax],0xa
   0x00005555555549a2 <+24>:	mov    QWORD PTR [rbp-0x8],rax
   0x00005555555549a6 <+28>:	mov    rax,QWORD PTR [rbp-0x8]//将变量地址存入rax作为函数返回值
=> 0x00005555555549aa <+32>:	leave  
   0x00005555555549ab <+33>:	ret    
End of assembler dump.
   
   0x0000555555554a0a <+38>:	call   0x55555555498a <mac()>
   0x0000555555554a0f <+43>:	mov    edx,DWORD PTR [rax]//取出rax中地址空间的值
   0x0000555555554a11 <+45>:	mov    rax,QWORD PTR [rbp-0x10]//将p引用中保存的值取出,该值为变量i的地址
   (gdb) info registers eax
	eax            0xffffddcc	-8756
	(gdb) p $rbp-0x14
	$3 = (void *) 0x7fffffffddcc
   0x0000555555554a15 <+49>:	mov    DWORD PTR [rax],edx//赋值给变量i
   和指针相对比可得:指针是直接改变其保存的变量地址,引用是通过保存的变量地址给被引用的变量赋值
另外一种函数返回值
函数原型
#include <iostream>
using namespace std;
int num;
int&  mac()
{
	num=10;
	return num;
	#不能返回栈中元素的引用,因为函数调用结束后栈空间会释放,此处只是举例
}
int main()
{
	int i= 10;
	int &p=i;
	p=mac();
	cout<<i<<endl;
	return 0;
}

汇编
Dump of assembler code for function main():
   0x0000555555554911 <+0>:	push   rbp
   0x0000555555554912 <+1>:	mov    rbp,rsp
   0x0000555555554915 <+4>:	sub    rsp,0x20
   0x0000555555554919 <+8>:	mov    rax,QWORD PTR fs:0x28
   0x0000555555554922 <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x0000555555554926 <+21>:	xor    eax,eax
=> 0x0000555555554928 <+23>:	mov    DWORD PTR [rbp-0x14],0xa
   0x000055555555492f <+30>:	lea    rax,[rbp-0x14]
   0x0000555555554933 <+34>:	mov    QWORD PTR [rbp-0x10],rax
   0x0000555555554937 <+38>:	call   0x5555555548fa <mac()>
   0x000055555555493c <+43>:	mov    edx,DWORD PTR [rax]
   0x000055555555493e <+45>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555554942 <+49>:	mov    DWORD PTR [rax],edx
   0x0000555555554944 <+51>:	mov    eax,DWORD PTR [rbp-0x14]
   0x0000555555554947 <+54>:	mov    esi,eax
   0x0000555555554949 <+56>:	lea    rdi,[rip+0x2006d0]        # 0x555555755020 <_ZSt4cout@@GLIBCXX_3.4>
   0x0000555555554950 <+63>:	call   0x5555555547d0 <_ZNSolsEi@plt>
   0x0000555555554955 <+68>:	mov    rdx,rax
   0x0000555555554958 <+71>:	mov    rax,QWORD PTR [rip+0x200671]        # 0x555555754fd0
   0x000055555555495f <+78>:	mov    rsi,rax
   0x0000555555554962 <+81>:	mov    rdi,rdx
   0x0000555555554965 <+84>:	call   0x5555555547a0 <_ZNSolsEPFRSoS_E@plt>
   0x000055555555496a <+89>:	mov    eax,0x0
   0x000055555555496f <+94>:	mov    rcx,QWORD PTR [rbp-0x8]
   0x0000555555554973 <+98>:	xor    rcx,QWORD PTR fs:0x28
   0x000055555555497c <+107>:	je     0x555555554983 <main()+114>
   0x000055555555497e <+109>:	call   0x5555555547b0 <__stack_chk_fail@plt>
   0x0000555555554983 <+114>:	leave  
   0x0000555555554984 <+115>:	ret    
End of assembler dump.

Dump of assembler code for function mac():
   0x00005555555548fa <+0>:	push   rbp
   0x00005555555548fb <+1>:	mov    rbp,rsp
   0x00005555555548fe <+4>:	mov    DWORD PTR [rip+0x20082c],0xe        # 0x555555755134 <num>
   0x0000555555554908 <+14>:	lea    rax,[rip+0x200825]        # 0x555555755134 <num>
   0x000055555555490f <+21>:	pop    rbp
   0x0000555555554910 <+22>:	ret    
End of assembler dump.

 0x0000555555554908 <+14>:	lea    rax,[rip+0x200825]        # 0x555555755134 <num>
 和之前相同同样是将地址放入rax中为后进行相同的操作
函数参数
   0x0000555555554a17 <+51>:	mov    rax,QWORD PTR [rbp-0x10]
   0x0000555555554a1b <+55>:	mov    rdi,rax
   0x0000555555554a1e <+58>:	call   0x5555555549ac <macp(int&)>
   对比可发现引用直接用其保存的地址将值取出,没有将地址取出保存至寄存器,而后利用寄存器取出值,即没有解引用这    一步

自增等操作

引用是弱化的指针,有很多相似的地方,不同的是当指针进行++操作时改变的是其保存的地址值,而引用则要通过地址寻找被引用的变量并改边其值

例如
#include <iostream>

using namespace std;

int main()
{
	int i=10;
	int *p=&i;
	int &pp=i;
	p++;
	pp++;
	return 0;
}

Dump of assembler code for function main():
   0x00005555555547aa <+0>:	push   rbp
   0x00005555555547ab <+1>:	mov    rbp,rsp
   0x00005555555547ae <+4>:	sub    rsp,0x20
   0x00005555555547b2 <+8>:	mov    rax,QWORD PTR fs:0x28
   0x00005555555547bb <+17>:	mov    QWORD PTR [rbp-0x8],rax
   0x00005555555547bf <+21>:	xor    eax,eax
   0x00005555555547c1 <+23>:	mov    DWORD PTR [rbp-0x1c],0xa
   0x00005555555547c8 <+30>:	lea    rax,[rbp-0x1c]
   0x00005555555547cc <+34>:	mov    QWORD PTR [rbp-0x18],rax
   0x00005555555547d0 <+38>:	lea    rax,[rbp-0x1c]
   0x00005555555547d4 <+42>:	mov    QWORD PTR [rbp-0x10],rax
   0x00005555555547d8 <+46>:	add    QWORD PTR [rbp-0x18],0x4
   0x00005555555547dd <+51>:	mov    rax,QWORD PTR [rbp-0x10]
   0x00005555555547e1 <+55>:	mov    eax,DWORD PTR [rax]
   0x00005555555547e3 <+57>:	lea    edx,[rax+0x1]
   0x00005555555547e6 <+60>:	mov    rax,QWORD PTR [rbp-0x10]
   0x00005555555547ea <+64>:	mov    DWORD PTR [rax],edx
   0x00005555555547ec <+66>:	mov    eax,0x0
   0x00005555555547f1 <+71>:	mov    rcx,QWORD PTR [rbp-0x8]
   0x00005555555547f5 <+75>:	xor    rcx,QWORD PTR fs:0x28
   0x00005555555547fe <+84>:	je     0x555555554805 <main()+91>
   0x0000555555554800 <+86>:	call   0x555555554670 <__stack_chk_fail@plt>
   0x0000555555554805 <+91>:	leave  
   0x0000555555554806 <+92>:	ret    
End of assembler dump.
指针++
 0x00005555555547d8 <+46>:	add    QWORD PTR [rbp-0x18],0x4
直接改变其保存的地址值,进行+4操作
引用++
   0x00005555555547dd <+51>:	mov    rax,QWORD PTR [rbp-0x10]
   0x00005555555547e1 <+55>:	mov    eax,DWORD PTR [rax]
   0x00005555555547e3 <+57>:	lea    edx,[rax+0x1]//这里edx等于11
   0x00005555555547e6 <+60>:	mov    rax,QWORD PTR [rbp-0x10] //取回i的地址
   0x00005555555547ea <+64>:	mov    DWORD PTR [rax],edx//赋值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值