博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++的引用类型的变量到底占不占用内存空间?
阅读量:7085 次
发布时间:2019-06-28

本文共 2026 字,大约阅读时间需要 6 分钟。

——by  karottc

分析一下 C++ 里面的引用类型(例如: int &r = a;  )中的 r 变量是否占用内存空间呢?是否和  int *p = &a;  中的 p 变量一样占用内存空间呢?

本文将给出答案。

直接看一个简单的例子:

#include 
using namespace std;int main(void){ int a = 6; int &r = a; int *p = &a; int x = r; return 0;}

 

接着我们通过  g++ testref.cpp -o testref -g  来编译之后,用gdb来加载它,看看 arpx 的地址分别是多少:

gdb

上图中 a 的地址为 0x7fffffffe208,用取地址符去获取 r 地址,值和 a 是一样的,其实,用 & 符号是不能获取到引用类型变量的地址的,因为引用类型的变量本身只是另一个对象的别名,用可感知的方式描述,就是它仅仅是一个名字而已,对它的任何操作都是相当于对另一个对象的操作,所以这个取地址操作也是一样。

但是,我们接着往下看,p 的地址是 0x7fffffffe218,和 a 的地址刚刚相差了 16 字节,接着看 x 的地址是0x7fffffffe20c,这个地址正好是 a的地址 0x7fffffffe208 + 4, 而 a 是 int 型,变量本身占用 4 字节,正常情况下, x 的地址应该是 p 的地址 0x7fffffffe218 + 8,这里 +8 是因为我的机器是 64 位的机器,所以指针类型占用 8 字节。现在这种情况应该是编译器做了优化,把 x 的放到了 a 的后面,同样的,x 的下一个变量的起始地址应该是 0x7fffffffe20c + 4 =0x7fffffffe210,这个地址和 p 之间刚好差了 8 个字节,也就是一个指针变量的地址,所以答案就很明显了。

即,我们现在可以猜测,r 是占用内存空间,并且占用的大小和指针变量相同大小。但是我们上面用gdb也看不了 r 的实际地址,所以这也只能是猜测,只是看似合理的猜测而已。

为了证明这个猜测,我们继续把可执行文件反汇编出来看看:objdump -d testref 得到的结果如下:

00000000004006cd 
: 4006cd: 55 push %rbp 4006ce: 48 89 e5 mov %rsp,%rbp 4006d1: c7 45 e8 06 00 00 00 movl $0x6,-0x18(%rbp) # int a = 6; a的地址 0x18 4006d8: 48 8d 45 e8 lea -0x18(%rbp),%rax 4006dc: 48 89 45 f0 mov %rax,-0x10(%rbp) # int &r = a; r的地址 0x10 4006e0: 48 8d 45 e8 lea -0x18(%rbp),%rax 4006e4: 48 89 45 f8 mov %rax,-0x8(%rbp) # int *p = &a; p的地址 0x8 4006e8: 48 8b 45 f0 mov -0x10(%rbp),%rax # 下面两行是为了后面的赋值做准备 4006ec: 8b 00 mov (%rax),%eax 4006ee: 89 45 ec mov %eax,-0x14(%rbp) # int x = r; x的地址 0x14 4006f1: b8 00 00 00 00 mov $0x0,%eax 4006f6: 5d pop %rbp 4006f7: c3 retq

 

我把对应处,都写在上面的注释里了。

所以,现在可以得到结论:引用类型的变量会占用内存空间,占用的内存空间的大小和指针类型的大小是相同的。 从上面的汇编代码可以看出,虽然引用是一个对象的别名,但是在汇编层面,和指针是一样的。

 

【本文首发于:】

2015.07.29

转载于:https://www.cnblogs.com/karottc/p/cpp-reference.html

你可能感兴趣的文章
教学思路ASP.Net之服务器控件:三、DropDownList、ListBox、CheckBoxList、RadioButtonList控件...
查看>>
puppet之用户管理
查看>>
技术分享连载(三十五)
查看>>
Quartz.net官方开发指南 第八课:SchedulerListeners
查看>>
redhat/centos学习笔记
查看>>
linux系统日志
查看>>
Oracle 11.2.0.3管理ASM实例
查看>>
【物联网中间件平台-06】RFID刷卡拍照
查看>>
【游戏开发备注之三】GameCenter登陆出现“无法识别此游戏”问题的两种解决方法...
查看>>
轻松获取海量长尾词 网站流量提升不再难
查看>>
sysbench的安装和做性能测试
查看>>
一道简单而又容易出错的题目
查看>>
报告:NVMe存储系统机遇与挑战
查看>>
从趣味游戏到排序算法(4)
查看>>
组策略妙用----通过组策略禁止域用户更改IP地址
查看>>
自助服务台——多渠道触发运维工单
查看>>
暴强贴:从.NET平台调用Win32 API
查看>>
AIX LV删除后,ORACLE数据库文件全部恢复成功
查看>>
BREW中几种常用的效果(淡淡浅出、半透明)
查看>>
jQuery如何得到tagName?
查看>>