1.引用
定义与条件
引用就是给变量取别名,引用和变量指向同一块空间。
1.引用必须初始化
2.引用不可改变为取引用其他的变量,讲其他变量赋予该引用是讲其他变量的值给引用赋值,但引用仍然跟原来的变量指向同样一块空间。(所以指针跟引用的功能不完全一致,指针可以随便改变,但是引用一旦定义就不能被改变)。
引用的作用
1.作为输出型引用
先拿C举例子,oj题中常常会给一个指针要你输入,这个指针所对应的值反应你最后输出呈现的值,那么就能说明一点,这个指针是和外部建立联系的变量,它的设计主要是因为返回参数不够真正需要返回的变量而使用指针进行类似于返回参数的功能。那么回到C++其实一样的,传入变量的引用意味着引用和变量属于同一位置,引用在函数调用时被改变,变量也在函数外同时被改变,以达到跟指针一致的作用,即输出到函数外。
2.引用做返回值
1.先讨论传值的返回
思考一下这个n是怎么实现传给ret的?1.如果这个n是在函数调用结束之后调用,似乎不太合适。因为这个函数调用完毕,函数内部都失效了,所以很奇怪,如果调用的都失效了不就是非法访问嘛,编译器肯定不是这样运行的。2.那如果在这个函数没结束return前把数传过去呢?那其实更不可能,函数没有调用完,跟外部是断开的,肯定不能实现在函数内部就把返回值传出去了的。所以编译器对于函数的返回值是这样处理的,实现它会在结束的时候创造一个临时变量,这个临时变量存在两种地方:如果临时变量占内存小,那么存在寄存器里;内存大,那么存在栈帧的下一层里,最后被拿去使用。下面两个的返回值实现是一致的。
2.引用返回的情况一 (返回值不在栈区上)
因为n是放在静态区的变量,并不属于栈区创建的临时变量。使用当我们用引用返回时,n的别名就是n,说明开辟的临时空间是n自己。使用时直接传。
3.引用返回的情况二 (返回值在栈区上)
返回值在栈区里,函数结束后,空间销毁了。n就是n的别名了,n开辟的临时变量也存在原地,而不是开辟另外的空间。而ret去访问n,可以访问,但是访问有发现,因为权限不受控制了。
引用返回正确使用下的作用:
1.节省内存;
2.修改返回值;
const的应用
![]()
使用const需要遵循的规律是,权限不能超过原来的权限。const缩小权限使得原来可读可写变成只能读不能写,ra的定义是可以的因为权限变小,而rb不行,b的权限是只可读,rb不能超过b的权限。那么如果想要rb符合,必须把rb前加const使得其权限跟b平行。
如果为了使得引用返回来减少拷贝的时间,那么最好在引用前面加const,这是为了保证不管函数调用传入的参数的权限。
想要引用中使用缺省必须在前面加const。常数只能读,不可以被赋予其他意思,如果没有const我们是不是就可以通过编译器改10这个数的含义了?很显然这太扯了,所以使用缺省要const表示a是10的别名,但是a不可被改变也就是10不能赋予其他意思。
![]()
另外,不能引用不可以直接进行类型转化。这是因为,所有的类型转换都是因为其传入前形成临时变量,而临时变量是有常性的跟上面常数有一样的属性。这导致下面我们想将a引用到ra时,临时变量限制住引用,所以处理的方法也就是在前面加const
double a = 3.14; const int& ra = a;
引用和指针的区别
1.在语法层面下,引用是变量的别名,指针是存放变量的地址;在底层,其实引用的实现也是通过指针完成的。
2.引用需要初始化,指针不需要初始化。
3.引用不能变为其他变量,但是指针可以变成同类型指针的不同变量。
4.引用的大小根据变量的大小来定,但是指针的大小是根据系统固定的。
5. 有多级指针,但是没有多级引用。
6. 引用编译器自己处理,指针需要显式解引用。
7. 引用比指针使用起来相对更安全。
2.auto
auto可以自动识别类型。C++使用的变量会类型会很长,当使用auto可以根据右边的值自动推导,十分方便。
语法糖tip:
下列代码是遍历数组,看起来十分麻烦的地方是需要求一下该数组的元素个数。
改进