深入了解C++引用

疑问:

1. 引用在初始化的时候赋值的,后面可以直接使用该引用,那么该引用是一个变量吗?

2. 如果是变量,那么肯定是有内存的?内存空间占用多少呢?里面存放的是变量的地址?还是变量的值?

3. 如果不是变量,在编译的时候应该是一个单独的符号,后面使用该符号的时候,怎么就知道使用哪里的值?怎么绑定的呢?

4. C++ pp 书中将其称为“别名”,或许如上面第3点,仅仅是变量的第二种符号?

通过实例进行深入分析

#include <iostream>

using namespace std;

int main()
{
    int i = 10;
    int &j = i;

    i = 1;
    j = 2;

    cout << "i: " << i << ", j: " << j << endl;
    return 0;
}

作为使用应用很六六的本人来说,i、j 打印出来的肯定是2(尴尬的自我感觉良好)。

带着结果去编译下,来看下符号表:

尴尬的是并没有看到 i 和 j 的符号,但是记得以前一本书上看过,即使是局部变量也是有符号的。

为了看到这个绑定关系,确认是否是前言中第3点猜想,还是要想办法看这个符号表的,把局部变量弄成全局就好。

代码稍微调整下:

#include <iostream>

using namespace std;

int i = 10;
int &j = i;

int main()
{
    i = 1;
    j = 2;

    cout << "i: " << i << ", j: " << j << endl;
    return 0;
}

重新来看符号表:

引用是独立存在的,有自己的内存空间,而且引用占用空间跟int 型的变量 i 还不一样,i 占用的是4个字节大小,而 j 占用了8个字节(这个看系统了,64位系统的地址是8字节的,这里别乱了)。

回到原来的代码,用gdb 来看看内存情况:

打印出来i、j 的值都是2,这个毋庸置疑的,但奇怪的是为什么&j 的地址和&i 的地址是一样的呢?

暂时先不管这个疑问吧,来看下代码运行:

介绍下rsp 和rbp:

%rbp is the base pointer, which points to the base of the current stack frame, and %rsp is the stack pointer, which points to the top of the current stack frame. %rbp always has a higher value than %rsp because the stack starts at a high memory address and grows downwards. 

回到代码,stack 上申请了0x20 大小的空间,-0x24 为i 的内存,-0x20为 j 的内存。

这里可以看到 j 占用的是-0x20 的内存,里面存放的是 i 的地址。

这里也解释了为什么符号表中看到的 j 的内存大小是 8 个字节了,系统是64位的。

来看下内存情况:

&i  和 &j 是一样的,上面已经确认了,即-0x24 对应就是内存地址0x7fffffffe20c,那么向上偏移4个字节就是 j 的内存,里面确认存放的就是 i 的地址。与上面的代码对应上了。

再来看下对 j 赋值:

从代码看,是先获取了 j 内存空间的值,也就 i 地址,然后修改 j 内存空间的值所指向的地址的值

可以猜想下,编译器可以这样的解析引用:

int* const k = &i;


j 等同于 *k,使用j 时,其实是使用 *k,即:

j = 2;
等同于:
*k = 2;

那么&j 可以等同于&*k,而&* 抵消,&j = k = &i;

这就解释了为什么打印出来 j 的地址和 i 的地址是一样的。

其实通过上面代码可以看出,引用的实质就是一个指针常量,因为是指针常量,所以必须要在初始化的时候赋值,所以不允许后面进行更改。而这些是编译器已经做好了,才会有上面的汇编代码。

如上面代码,k 为指针常量,k 的内存空间应该是在常量区,k 的内存里存放着 i 的地址,j 相当于 *k,即使对指针常量的“引用”,指向了确切的变量。

总结:

  • 引用在使用的时候可以直接看成变量的别名,当做变量直接使用;但实质上是指针常量;
  • 引用实质是一个指针常量,所以需要在定义的时候初始化,后面是不允许改变的;
  • 引用有自己的内存空间,空间大小就是初始化时变量的地址的大小;

 

 

参考:

Understanding C by learning assembly - Blog - Recurse Center

Data Center

An Insight to References in C++ - CodeProject

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

私房菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值