TearSnow

C++引用和指针有什么区别?如何实现?

引用在进程中是否会分配内存?

C++ primer中说:引用就是对象的另一个名字。

C++ primer中说:指针用于指向对象,保存的是另一个对象的地址。

从字面意义上,感觉引用并没有分配内存,而指针是分配了内存的,于是写了个小程序进行测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
int main()
{
long val = 1;
long &r_val = val;
const long &const_r_val = val;
const long &const_r_tmp = 123;
long *p_val = &val;
printf("val address: 0x%lxn", &val);
printf("r_val address: 0x%lxn", &r_val);
printf("const_r_val address: 0x%lxn", &const_r_val);
printf("const_r_tmp address: 0x%lxn", &const_r_tmp);
printf("p_val address: 0x%lxn", &p_val);
void *tmp;
tmp = &r_val;
const void *const_tmp;
const_tmp = &const_r_tmp;
tmp = &p_val;
return 0;
}

采用g++编译得到如下结果:

1
2
3
4
5
val   address: 0x7fff7377ee48
r_val   address: 0x7fff7377ee48
const_r_val   address: 0x7fff7377ee48
const_r_tmp   address: 0x7fff7377ee50
p_val   address: 0x7fff7377ee40

可以看出对引用取地址(&)跟变量取地址(&)都是得到同一个地址值,而对指针取地址(&)得到的是另外一个地址,好像引用真的没有分配内存,这是真的吗?

其实上不然,从C++语义上说,引用就是对象的另一个名字,并没有具体的指定另一个名字的具体实现,根据编译器的不同,引用的实现也不一样。

我们通过objdump –d a.out进行反编译可知:

1
2
3
4
5
6
7
8
long val = 1;
movq  $0x1,0xffffffffffffffe8(%rbp) //将立即数1复制给val所在的内存
long r_val = val;
lea   0xffffffffffffffe8(%rbp),%rax //将val所在的内存地址赋值给rax
mov   %rax,0xfffffffffffffff0(%rbp) //将rax赋值给r_val所在的内存
long *p_val = &val;
lea   0xffffffffffffffe8(%rbp),%rax //将val所在的内存地址赋值给rax
mov   %rax,0xffffffffffffffe0(%rbp) //将rax赋值给p_val所在的内存

我们可以看出实际上指针和引用的在g++编译器中的实现是一样的,既然分配了内存,为何&r_val == &val?

我们来继续看看反汇编代码:

1
2
3
4
5
6
tmp = &r_val;
mov   0xfffffffffffffff0(%rbp),%rax //将r_val变量中存的内存地址赋值给rax
mov   %rax,0xfffffffffffffff8(%rbp) //将rax的值赋值给了tmp
tmp = &p_val;
lea   0xffffffffffffffe0(%rbp),%rax //将p_val的内存地址赋值给了rax
mov   %rax,0xfffffffffffffff8(%rbp) //将rax的值赋值给了tmp

对于取地址运算(&),g++编译器对于引用和其他变量的处理是不一样的,引用调用的汇编指令mov,得到引用所在内存存储的变量内存地址,而其他变量的取地址(&)运算调用的是汇编指令lea,得到变量本身的存储地址,于是有了引用不分配内存的假象。

上述分析针对于linux下的g++编译器,传说在VC中进行编译会得到不同的结果,在debug编译下,引用是会分配内存的,而在release编译下,引用不分配内存,直接调用变量,有兴趣的童鞋可以去试试。

  Yabo个人博客原创文章,任何媒体、网站或个人未经本站同意不得转载、复制或者伪原创;如果你喜欢本文,可以通过下面的分享按钮来分享本文。

标签: 该日志由 Yabo 于2015年08月06日发表在 Programming 分类下, 您可以发表不同观点
原创文章,转载请注明: C++引用和指针有什么区别?如何实现? - Yabo个人博客
Yabo
扫一扫
个人微信号
个人微信号