C++中引用与普通变量内存消耗差异及汇编问题解析
C++引用与普通变量的内存、访问开销差异(基于提供的无优化汇编输出)
1. 引用与普通变量的内存消耗差异
从x86-64环境下无优化编译的栈布局可以直接算出两者的实际占用:
- 普通int型变量
numVarible放在栈偏移[rbp-12]的位置,占用4字节,和int类型本身的大小完全一致 - int型引用
numReference放在栈偏移[rbp-8]的位置,占用8字节,和x86-64架构下的指针大小完全一致
也就是说,在无优化编译的实现下,引用本质就是通过指针存储被引用对象的地址,所以单看栈上的内存占用,引用的开销等于同架构下的指针大小,在x86-64环境下是同类型普通int变量的2倍。
需要说明的是,这只是无优化编译的表现,当开启最高等级优化后,编译器大多会直接把引用作为被引用对象的别名处理,不会给引用本身分配任何栈空间,此时引用不会产生任何额外内存开销。
2. 返回引用时汇编行数变多的原因
把修改前后的返回指令流程拆开对比就能明确原因:
- 原返回普通变量
numVarible的流程是单步:直接从固定栈偏移[rbp-12]位置,把存储的4字节int值读到返回值寄存器eax里,对应单行汇编mov eax, DWORD PTR [rbp-12] - 修改为返回引用
numReference后的流程分为两步:- 先从栈上的引用存储位置
[rbp-8],把之前存的被引用对象的8字节地址读到rax寄存器,对应mov rax, QWORD PTR [rbp-8] - 再拿rax里存的地址做间接寻址,从地址指向的内存位置读出4字节的int值,放到eax作为返回值,对应
mov eax, DWORD PTR [rax]
- 先从栈上的引用存储位置
本质上,无优化编译下的引用是独立的栈存储单元,存的不是被引用的值本身,而是指向被引用对象的地址。要获取引用对应的实际值,必须先读出这个地址,再顺着地址读目标值,多了一层间接寻址的流程,自然就比直接访问固定栈位置的普通变量多了一行指令。
这种额外的指令开销也只存在于无优化编译场景,开优化后编译器会直接消掉引用的存储和间接寻址过程,访问逻辑和普通变量完全没有差异。
内容的提问来源于stack exchange,提问作者mariolu
相关产品推荐
相关产品推荐

