目录
引用概念
引用的用法
做函数形参
优点一
优点二
引用做返回值
让我们更深入的了解引用与指针
语法层引用与指针完全不同的概念
站在底层的角度看指针与引用
引用概念
在语言层面上:引用不是定义新的变量,而是给已存在变量再取一个别名,编译器不会为引用新开一个空间,他和他的引用的变量共用一块内存空间,
如李逵在家叫“铁牛”在外叫“黑旋风”
看代码,为a取别名
int main()
{
int a = 10;
int&b = a;//为a取别名b
return 0;
}
内存查看
打开内存发现他们都是一个地址。
会发现a,b地址相同
他们的地址都是相同的,所以我们可以认为引用并没有开空间,也只是在一块空间上多了个别名,依靠这个别名也可以访问该空间数据。
监控查看
我们更改别名的数据,同时也会把被取别名的数据更改
所以可以通过修改b的数据,从而修改a的数据。这里是十分重要的。
引用的用法
做函数形参
优点一
这里的func1传值做参数,需要拷贝a的数据。
然而func2为引用做参数,无需拷贝数据,这_a为a的引用,用同一块空间
优点二
引用可以通过改变形参来改变实参。(类似指针的用法)
引用做返回值
正常的函数返回值接收
int func()
{//....
return 10;
//....
}
//......
int ret=func();
//..
有两个情况:
一、函数返回值为引用,接收变量不为引用,减少一次数据的拷贝。
这里有个隐患,当func函数结束会销毁栈帧,OS回收数据,但是是否会重置数据就看编译器了。所以我们引用返回值尽量都是引用静态变量为返回值。
int&func()
{
static int a=10;
return a;
}
二、函数返回值为引用,接收变量也为引用,直接没有数据拷贝(两次都没有了)。
这里引用的对象必须是static的变量,否者在未来,一旦有一次任意函数调用都有可能覆盖值。
看我们的流程,既然ret是a的引用,哪为什么还要有临时空间呢?因为在函数结束后只要是return 数据,都一定要放入临时空间保存,无论是否是引用,因为一旦栈帧销毁了,我们就不能再去访问函数内的操作,所以这个时候就要靠临时空间将我们需要的数据带出来,可能是寄存器也可能是上一层栈帧的头部位置开空间做临时空间。在语言层面来看:临时空间不会开空间,并不是说可以取消临时空间
让我们更深入的了解引用与指针
语法层引用与指针完全不同的概念
指针:开空间,存放变量地址;
引用:不开空间,仅仅是变量的别名
//.Cpp
int main()
{
int a=1;
int& b=a;
int*p=&a;
b=2;
*p=3;
return 0;
}
上面的知识点可以看看,但是不要靠背他们
其实我更喜欢指针,可以看到细节,都在自己的掌控之中
站在底层的角度看指针与引用
先让我们学两个指令:
mov a b 将b数据放入给a中
lea eax a 将a的地址放入寄存器eax中
观察汇编代码,我们惊奇的发现:pa指向a与ra引用a的操作居然是一模一样的。
这里说明了,引用其实就是指针,但是他的操作逻辑操作不是我们程序员的事情,是编译器的事情。
所以虽然我们只要关注语言层面的引用,但是底层的引用我们也不能不知道。