必看!帮你C++更快入门2——引用篇

引用

前言

本章我们将学习C++中的引用内容。此内容也是相当的重要,因为引用的话,它是对标我们此前在C语言学习的指针,我们都知道指针对于C语言的根基。
所以,引用对于整个C++的学习是至关重要的

引用的内涵

相信大家从小到大,身边的人或者自己或多或少也被别人取过“外号”吧?例如有个人叫做小红。那么比较调皮的同学可能就会给这位小红同学取外号,会叫他“猴子”、“西红柿”之类的外号。那我们知道,这个“猴子”、“西红柿”都是指的同一个人,也就是小红。

所以,像这给变量(也就是上面所说的小红)取别名(也就是外号)的行为,就叫做引用。

引用的语法规则以及注意事项

假设我们这里定义一个int类型的变量,我们要给它取别名,语法上怎么操作呢?
代码如下:

int main()
{
   int a = 10;
   int & b = a;//这里的b就是a的别名,a就是b,b就是a
}

所以引用的语法规则就是:被引用对象的类型 + & +引用的名字(也就是外号)我们再举一个例子:

int main()
{
   double c = 3.14;
   double & d = c;//说明了d是c的引用,d就是c,c就是d
}

此外,我们需要注意的是,一般我们只给变量作引用,数组函数之类的引用并没有多大的意义。

引用的特点

(1)我们可以对一个变量取多个引用,即:

int main()
{
   int a = 10;
   int & b = a;
   int & c = b;//这里的b就相当于a了,给b取别名就相当于给a取别名
} 

这里的b和c都相当于这里的变量a,也就是它们表现的都是同一块空间。我将作图表示:
在这里插入图片描述
可以看到,a、b、c都是指向同一块内存空间

那么,接上面的代码,我们再来看一组代码:

int main()
{
   int a = 10;
   int & b = a;
   int & c = b;
   int & d = a;
   //自此,abcd都指向了10,我们来看看下面的代码
   int x = 20;
   c = x;
} 

下面加的这两行代码是什么意思呢?谁发生了改变呢?提示一下,C++是从右向左赋值的。
3
2
1
答案揭晓,是将20赋值给了c,又因为c是a的别名,bd也是,所以abcd都由原先存放的10变成了20;也就是说
在这里插入图片描述

这就从侧面反映出了,假如bcd全都是a的别名,对a进行++,也就是对bcd也++,具有一致性。

引用的功能

(1)

以前我们想交换两个变量的值,通常是把两个两个的地址一一传过去,用指针变量接收,再通过中间变量进行一个交换。

那么我们现在学习了引用,也明白引用就是一个变量的别名,那么我们可以别名来接收需要交换的变量,因为那个别名也指向那个需要交换的变量

具体的操作,如下:

void Swap(int & x,int & y)//x是a的别名,y是b的别名
{
   int tmp = x;
   x = y;
   y = tmp;
} 
int main()
{
   int a = 5;
   int b = 10;
   Swap(a,b);
   return 0;
}

这样看,我们实现了在不使用指针的前提下,改变了两个变量的值。

(2)

我们在使用结构体的使用,假如里面的成员很大的话,我们又想对这个结构体变量初始化,那么再创建一个变量的话,就会占用内存很大的一块空间,运行效率也会下降,所以我们用引用来接收这个结构体变量。在这里插入图片描述

代码如下:

struct A
{
   int arr[100];
   double d;
}
void structinit(struct A & aa)//aa是a的别名,用来代替a来对a进行初始化
{
   int i = 0;
   for(i = 0;i<100;i++)
   {
       aa.arr[i] = i;//对数组arr进行逐个的赋值
   }
   aa.d = 3.14;
} 
int main()
{
   struct A a;//创建结构体a变量
   structinit(a);//把a传过去
   return 0;
}  

传值返回

我们的函数都很多的返回值类型,例如void,就是不返回任何值;int,就是返回整型值,传引用返回,就是返回某个变量的别名

在开始讲传引用返回时,我们来看看函数的普通返回类型有什么特点

我们先来看一段代码正不正确:

int func(int i)
{
    return i;
}
int main()
{
   int a = 5
   int x = func(a)++;
   return 0;
}

上面我对函数func的返回值进行了++,那么这样做是对的吗?在判断对错之前,有一个知识大家得了解

对于任何函数,只要这块函数中的程序运行结束了,那么这块函数空间就会还给操作系统了,所以上述的func函数是否实实在在的把“i”返回到主程序(main函数)中呢?显然答案是否定的,因为在返回i的过程中,中途会产生一个临时变量,才把这个临时变量返回到main函数中,而临时变量又具有常性,具有常性的意思就是无法被修改,就比如我们的10它也是常量,我们无法去修改10这个常量是一个道理。
在这里插入图片描述

所以我们这里的func(a)++是可以被执行的吗?那是不可以的,因为func(a)是一个临时变量,具有常性,无法被修改.

传引用返回

那么返回值是某个类型的返回值就是传引用返回,那么,我来为大家科普一下传引用返回的知识点

假如返回某个变量的别名,那个变量出了函数还在的话,那就是安全的;假如出了函数那个被返回的对象出了函数就销毁了,那么就是不安全的

第一种情况,代码如下:

int & func(int ret)
{
    return ret;
}
int main()
{
   int a = 10;
   int x = func(a);
   return 0;
}

上述代码是不安全的。用x来接收ret的别名,但是出了func函数后,func里面的东西就已经归还操作系统了,假设后面有人用了这一块已经被归还操作系统的func内存空间,就有可能改变了这个ret的值,那么返回的就不是原先的ret了,所以这种行为是不安全的

第二种情况,代码如下:

typedef int Sldatatype;
typedef struct Slist
{
   Sldatatype *arr;
   int top;
   int capacity;
}Sl;
int & func(Sl & sl,int i)
{
   return sl->arr[i];
}
int main()
{
    Sl sl;
    Slintt(&sl);//对sl初始化
    Slpush(&sl,1);//对顺序表打入一个数据1
    int i = 0;
    int x = func(&sl,i);<------------
    return 0;
}

箭头指向的代码行就是正确的,因为sl->arr[i]这块内容是通过动态内存扩展的空间,只要我们不主动释放,这块空间会一直存在,所以出了这个函数,sl->arr[i]的内存还是存在的,所以返回其别名是安全的。

引用与指针的不同

(1)引用必须初始化,指针初不初始化都可
因为引用一开始就得确认是谁的别名,不然取引用就没有意义了。指针不初始化就是空指针NULL
(2)引用无法改变指向,指针可以
我是你的别名就是你的别名,无法成为别人的别名。但是指针就可以改变指向的对象,我可以存放a的地址,那我也可以转而存放b的地址
(3)引用不开空间,指针开空间
(4)两者的sizeof函数不同
在64为位操作系统中,指针位8个字节的大小。而引用就是某个类型的大小,例如a是int型,b是a的别名,那么sizeof(b)= 4;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值