C++引用、内联函数、auto关键字解析

发布时间:2024-01-04 14:00

目录

引用

内联函数

auto关键字


引用

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

\"C++引用、内联函数、auto关键字解析_第1张图片\"

这里的变量a 共有三个引用 a、b、d、e是共用同一块空间的,也说明只有改变四个中一个,其他三个也会跟着改变。

\"\"

可以看出 地址是完全相同的

\"\"

当给b赋值时

\"\"

其他的值也跟着改变

引用的特性:

1.引用再定义时必须初始化

2.一个变量可以有多个引用

3.引用一旦引用一个实体,再不但引用其他实体


取别名原则:对原引用变量、权限只能缩小或不变,不能放大

\"C++引用、内联函数、auto关键字解析_第2张图片\"

 引用常量的处理方法:\"\"


\"\"

 这里的类型转换 在底层中 内存会分配一个临时变量

这个临时变量 是用来存储int类型的值。(这个过程叫:隐式类型转换

临时变量具有 常性

例子:

\"\"

 这里为什么会报错? :刚才提到了 在隐式类型转换 会出现一个 临时变量 又因为临时变量具有常性  而根据取别名原则,不允许扩大。所以这里需要让int的权限边小

\"\"

但是这里需要注意 f之所以需要减小权限 就因为它引用的是临时变量,所以在底层中 f引用的就不是a了 

\"\"

 可以看出 f和a的地址是同的 f引用时临时变量,而不是a


引用使用场景

1.做参数

当你传参时,若你传的是值时 底层中 是拷贝参数的值 再传给函数 这个过程时有损耗的。当值小时可以忽略不记 但是当你频繁使用这个函数,并且这个值 非常大时 损耗是非常大的

所以 这里可以用引用做参数 引用并不用拷贝它的值 效率是比较高的。

\"C++引用、内联函数、auto关键字解析_第3张图片\"

引用做参数的好处:

若传值,那么编译器需要拷贝给参数,若传的参数大,且次数多,那么损耗很大,若是引用,那么直接用地址该,损耗是较小的。(若用指针的地址,也是一样的,损耗较小,与引用差不多)

引用做参数的意义:

1.输出型参数,减少拷贝,提高效率

传值、传引用效率比较:

以值作为参数或者返回值类型,在传值和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时拷贝,因此用值作为参数或者返回值类型,效率是非常底下的,尤其是当参数或返回值类型非常大时,效率就更加底下

 2.做返回值

\"C++引用、内联函数、auto关键字解析_第4张图片\"

 这样做看似没问题,其实是没考虑到函数的栈帧问题。

ret是n的引用 他们是公用一个空间的。当count返回后,函数栈帧销毁,那么n的空间就会销毁,那么ret的空间也会销毁。

但是你仍然可以去访问这个ret 就造成了越界访问。

\"C++引用、内联函数、auto关键字解析_第5张图片\"

\"\"

这里之所以第一次会正常打印,因为编译器还没有及时销毁函数栈帧,但是接下来几次,就是随机值了,因为ret的空间已经被销毁,归还给系统了,所以变成了随机值,也造成了越界访问

但是也有例外,当你把n的权限扩大,扩大成静态变量,不与函数栈帧销毁时一起销毁,就不会造成此类问题

\"C++引用、内联函数、auto关键字解析_第6张图片\"

\"\"

 可以看出,三次都是正常打印。


当用值返回时:

用值返回,中间是有一份临时变量,当此数多且多次返回时,会造成效率低下,而用引用返回时,时不会有这一份临时变量的,效率更高。

引用返回与值返回:

如果函数返回时,出了函数作用域,如果返回对象,还在(还没返还给系统)则可以使用引用返回,如果返回对象不在(已经返还给系统)就不能用引用返回,必须用值返回

\"C++引用、内联函数、auto关键字解析_第7张图片\"

\"C++引用、内联函数、auto关键字解析_第8张图片\"

 在汇编中 他们的汇编指令其实是相同的


引用和指针的不同点:

1.引用在概念上定义一个变量的别名,指针存储一个变量地址。

2.引用在定义时必须初始化,而指针没有要求(但建议初始化)

3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时间指向任何一个同类型的实体

4.没有NULL引用,但有NULL指针

5.在sizeof中计算的含义不同

引用的结果是类型的大小

指针始终是地址空间所占字节个数 (4/8)

\"C++引用、内联函数、auto关键字解析_第9张图片\" 

\"C++引用、内联函数、auto关键字解析_第10张图片\"

 6.引用自加即实体增加1 指针自加即指针向后偏移一个类型的大小

\"\"

7.有多级指针,但没有多级指针

8.访问实体方式不同,指针需要显式解引用,引用编译器自己处理

9.引用比指针使用起来相对安全


内联函数

以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建议栈帧的开销,内联函数提升程序运行的效率

内联函数(inline)是C语言宏(define)升级过来的。

\"C++引用、内联函数、auto关键字解析_第11张图片\"

 很多人会犯的错误 就是每个参数都要加括号 不然会出错,这样导致了C语言的宏不够好。

C语言宏的缺陷:C的宏不支持调试,并且容易出错

内联函数 只需要在函数的返回类型前+ inline就可以

\"C++引用、内联函数、auto关键字解析_第12张图片\"

但是在汇编中,无法查看编译器对inline展开 这里需要一些设置

\"C++引用、内联函数、auto关键字解析_第13张图片\"

\"C++引用、内联函数、auto关键字解析_第14张图片\"

 inline的优点:debug支持调试,不容易写错,与普通函数写法相同

inline的特性:

1.inline是一种空间换时间的做法,省去调用函数额外开销(建立栈帧)但是代码很长(通常为10行,取决于编译器)或者有递归的函数不适应作为内联函数

2.inline对于编译器而言只是一个建议,编译器会自动优化,如果定义inline的函数很长或者递归函数等等,编译器优化时会忽略掉内联

3.inline不建议声明和定义分离,分离会导致链接错误,因为inline被展开,就没有函数地址了,链接就会找不到。(建议直接在.h(声明)内直接实现 


auto关键字

自动推导赋值的类型

\"C++引用、内联函数、auto关键字解析_第15张图片\"

 typeid 它是打印类型名 返回的是字符串

\"C++引用、内联函数、auto关键字解析_第16张图片\"

 \"\"

 当然 也可以推导其他类型

\"C++引用、内联函数、auto关键字解析_第17张图片\"

\"\"

 \"\"

auto的意义之一:变量名很长时,可以用auto自动推导 


范围for

依次取 arr 中的数组 赋值给e 用auto自动判断

\"C++引用、内联函数、auto关键字解析_第18张图片\"

 for循环后的括号由冒号“:”分为两部分 第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

\"\"

 引用取arr的值赋值给e 所以e无法直接改变arr里的值。但可以用引用 改变

\"C++引用、内联函数、auto关键字解析_第19张图片\"

\"\" 这里其实可以不用auto 可以自己指定类型 int  但是用auto更方便 


auto不能作为函数形参类型 auto不能作为函数返回类型

auto不能作为数组类型 auto不能作为缺省参数

范围 for的使用条件

1.for循环迭代的范围必须是确定的

对于数组而言,就是数组中第一个元素和最后一个元素的范围:对于类而言,应该提供begin和end的方法,begin和end就算for循环迭代的范围

\"C++引用、内联函数、auto关键字解析_第20张图片\"

这里之所以错误,因为传参传的是地址 范围是不确定的,所以不能使用范围for


若本篇文章对您有帮助,希望能获得您的赞!

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号