和C语言相比,C++引入了左值引用,本文介绍左值引用的实现原理。
1. 测试
1.1 编译环境
- aarch64-linux-gnu-g++ 6.3.1
1.2 C++ code
1 | void test_reference(int &ra) { |
1.3 汇编code
1 | 0000000000400770 <_Z14test_referenceRi>: |
2 分析
2.1 普通变量
普通变量a的赋值
1 | int a = 1; |
对应汇编
1 | 4007c0: 52800020 mov w0, #0x1 // #1 |
变量a是局部变量,存储在栈内fp + 44的地方,大小为4
2.2 引用
先看引用的初始化
1 | int &ra = a; |
对应汇编
1 | 4007c8: 9100b3a0 add x0, x29, #0x2c |
也就是,引用ra本身存储在栈内fp + 56的地方,大小为8, 里面存储的是变量a的地址即fp + 44
再看引用的赋值
1 | ra = 2; |
对应汇编
1 | 4007d0: f9401fa0 ldr x0, [x29,#56] |
也就是,先将引用对应的变量的地址load出来, 再将具体赋的值store回变量的地址。
2.3 指针
先看指针的初始化
1 | int *pa = &a; |
对应汇编
1 | 4007dc: 9100b3a0 add x0, x29, #0x2c |
指针pa指向普通变量a, 其存储在栈内fp + 48的地方, 大小为8, 存储的内容为变量a的地址即fp + 44
再看解引用指针
1 | *pa = 3; |
对应汇编
1 | 4007e4: f9401ba0 ldr x0, [x29,#48] |
和引用类似,先将指针指向的变量的地址load出来, 再将具体赋的值store回变量的地址。
2.4 引用和指针作为形参
从前面test_reference和test_pointer的汇编代码对比来看
- 引用和指针传参,实现是相同的, 传入的都是变量a的地址
- 修改引用或解引用指针,都会反映到变量a
3. 总结
- 从语法上讲,引用是变量的别名。 但从编译器实现来看, 为其分配了存储空间,初始化为指定变量的地址。
- 引用可以看作是constant pointer, 对引用的访问,可看作被引用变量的间接访问。