引用和指针

引用的详解

引用的汇编底层角度
在这里插入图片描述

如上图所示在VS2022中反汇编的汇编语言看出来。源代码int &b = a和int* const c = &a的汇编代码是一模一样的,都是把 a 变量的地址放入eax寄存器中,然后在赋值给变量b和c。这很明显是个指针行为也证明了引用是指针常量实现的,也可以把引用当作指针常量来理解。

既然引用是指针常量实现,那么这个"别名"变量也是有内存空间占用的,且占用大小同指针大小一样。

可是我们sizeof运算别名只能得到原名对象数据类型大小,这是因为sizeof对引用的特殊处理了。

既然"别名"也是变量,那肯定也有内存地址,可是我们对别名取地址时,只能得到原名对象数据的地址,这是因为编译器改变了引用的取地址含义,这样想要获得"别名"变量的地址变得很困难,但是我们记住"别名"变量有地址,大小和指针一样
指针行为

class Person { public: int age; };
Person p1;
Person *ptr1 = &p1; 
cout << ptr1->age << endl;//输出无规则的脏数据,因为没有初始化。。。等价于(*ptr).age
  • 为什么指针用->?因为这是一个指针行为,具体汇编角度来看,会把指针指向的地址放入寄存器,再从寄存器读出地址去访问。

此时再加上以下三行代码

Person& pp = p1;
cout<<ptr1->age<<endl;//输出0
cout<<pp.age<<endl;//输出0
  • 为什么引用别名的pp要用.呢?明明引用的底层本质也是指针行为。具体来说,我觉得无论是-> ,.都是指针行为访问数据。具体情况为ptr指针变量的变量本身的地址与指向的p1是非连续的。而后者pp别名因为本身的变量地址被隐藏而形成了"别名"的特性,使得和原名p1假装连续了。
  • 而之所以前面的age输出脏数据,而加上别名就总输出0。是因为这是编译器看到别名而带动的初始化。(不重要,要有不使用未初始化数据的好习惯)
指针和引用的区别

指针简单来说是一个变量存储一个地址,然后根据指针类型的那个类型如int来按照int类型规则指向那块内存。

引用简单来说就是对一个其他的变量(原名变量)起了个别名。对别名的操作本质上都是对原名变量的操作。

引用的本质就是指针

具体区别如下

  • 二者都是变量,从变量的角度出发是有占用内存的地址和占用内存大小的。都是跟随系统架构位数决定的,也就是内存寻址能力。如x86架构的大小都是4B能寻址4GB内存,指针内存地址也是可以通过&取值符号求得。但是,引用的这个"别名变量"很难求得占用内存的地址和占用内存大小,都被编译器优化了。上述详解有说明
  • 既然指针变量的地址可以求得,也就说可以用另外的指针变量存储嵌套形成多级指针,但是,因为没办法,只有一级
  • 指针的这个变量值可以改变,意味着指向可以修改,但是,引用底层是指针常量实现的,无法改变指向。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值