一、引用概述
引用只是指针的一个拓展,你要想听懂引用的内容,最少需要先去了解指针是如何工作的。指针和引用是c++中常被提及的两种关键字,它们实际上是一回事。指针和引用在使用上来说,其实是一回事。当然,我们如何写它们,怎么用它们还是有些不同,但是本质上来看,引用就是指针,它俩就是一回事。
引用就是指对现有变量引用的一种方式,和指针不同,指针中要先创建一个指针变量,然后给它赋值nullptr或者其它等于0的值,引用不能这么做,因为“引用”必须引用一个已存在的变量,引用本身并不是一个新的变量。它们并不真正占用内存。它们也不像你之前用的典型数据类型变量那样存储数据,因为它只是其它变量的引用。
二、引用简单使用
比方说我创建了一个整型变量a赋值为5。
int a=5;
如果我想创建这个变量的引用,我可以这样写:
先是变量类型,接着是&,但要注意&是变量声明的一部分,关于指针,我们知道:&加上已存在的变量前可以指向它的内存地址,在这里不一样,&实际上是变量类型的一部分,这里它不是贴着一个已经存在的变量,他是变量类型的一部分,记住它,并不是有&符就一定是取地址或一定是引用,具体情况要看这里的上下文,在这里因为它挨着变量类型,所以是引用。我们接着写给这个引用命名为ref,让它等于a。
int& ref=a;
就是让它等于一个已存在的变量即可。这样我们就创建了一个别名(Alias)。因为这个ref“变量”,加引号的意思是它其实不是变量,其实是引用。这个ref变量并不真正存在,它只存在在我们的源码里。
如果你现在编译这个程序,你不会创建两个变量a和ref,只有a。我们现在能做的就是把ref当成a使用。
我们来设置ref为另一个值:
ref=10;
我们来输出a
log(a);
运行程序,结果如下:

在任何情况下,ref就是a,我们只是给a起了一个别名。在这个例子中,我们引用的不是一个指针,编译器没有必要创建一个新的变量。
这里只是源码的一种操作,我们希望给某个变量一个别名,引用能让写代码更好写一下。
三、稍微复杂点的引用
假设我们在上面的基础上,增加一个函数,使得输入的整数递增,
void Increment (int value)
{
value++;
}
如果我们把a作为参数放进这个函数中,
Increment (a)
这里将要发生的是,由于我们是传值调用,这里没用指针或者引用。所以调用过程中程序将会拷贝参数值5到这个函数里,直接拷贝,这里将会创建一个新的变量value,就像在Increment函数里面,声明了一个变量value,并赋值给5.然后value++。
我们测试来证明一下:

a没有增加。只是value增加了。
我们这里需要的是引用传递,而不是值传递,让这个变量a递增。我们应该怎么做呢?
怎么做才能通过把变量传递进函数来真正改变这个变量a的值。上次我们提到指针是内存地址,所以理论上将我们可以不传递5这个值,我们可以直接传递a这个变量的地址。
因为我们可以在函数里找到这个变量的地址,看到数字5,然后加以更改。我们可以通过内存地址完成写入,因为我们把内存地址传递进函数里。我们如下修改代码:

把函数的形参换为一个指针,还是使用的value变量。调用函数的时候是把a的内存地址传递给函数而不是a。函数里逆向引用,修改地址存储空间里的值而不是地址的值。
指针就是地址,实际上是一个整数,如果直接在后面++,而不在前面带星号的话,它就会增加内存地址的值而不是实际存储的数值。
运算结果如下:

这里要注意运算符的优先级,需要添加小括号改变运算次序;运行结果如下:

但是这个视频是关于引用的,如果使用引用的话会更简单的实现上面的功能,用更少的代码。我们可以把这里的指针引用改成引用的形式。这样做的好处是我们可以去掉这里的逆引用*,改回原来的value++;调用函数时也不需要传递地址,只需要传递变量a。代码如下所示:

上面图中,我们采用的是引用传递,完成了指针传递相同的功能。源码看起来更简单了。
这是唯一的区别。
最重要的一件事情,引用一旦声明,不可更改它所引用的对象。
如下:int& ref=a;
ref=b;
这里实现的是把b的值赋予a,而不是引用ref为b。
同时这意味着当你声明引用的时候必须将一个实际的变量赋值给它,因为它必须是某对象的引用。
记住它他是某物的引用不是实际的变量。
四、如果确实想改变引用怎么办?
引用这并不是真正的变量,我们需要创建一个变量指向a,然后在让它指向b,这里一直说指向是想让你明白我需要使用指针。

1297

被折叠的 条评论
为什么被折叠?



