发布时间:2024-01-04 14:00
目录
引用
内联函数
auto关键字
引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。
这里的变量a 共有三个引用 a、b、d、e是共用同一块空间的,也说明只有改变四个中一个,其他三个也会跟着改变。
可以看出 地址是完全相同的
当给b赋值时
其他的值也跟着改变
引用的特性:
1.引用再定义时必须初始化
2.一个变量可以有多个引用
3.引用一旦引用一个实体,再不但引用其他实体
取别名原则:对原引用变量、权限只能缩小或不变,不能放大
这里的类型转换 在底层中 内存会分配一个临时变量
这个临时变量 是用来存储int类型的值。(这个过程叫:隐式类型转换)
临时变量具有 常性
例子:
这里为什么会报错? :刚才提到了 在隐式类型转换 会出现一个 临时变量 又因为临时变量具有常性 而根据取别名原则,不允许扩大。所以这里需要让int的权限边小
但是这里需要注意 f之所以需要减小权限 就因为它引用的是临时变量,所以在底层中 f引用的就不是a了
可以看出 f和a的地址是同的 f引用时临时变量,而不是a
引用使用场景
1.做参数
当你传参时,若你传的是值时 底层中 是拷贝参数的值 再传给函数 这个过程时有损耗的。当值小时可以忽略不记 但是当你频繁使用这个函数,并且这个值 非常大时 损耗是非常大的
所以 这里可以用引用做参数 引用并不用拷贝它的值 效率是比较高的。
引用做参数的好处:
若传值,那么编译器需要拷贝给参数,若传的参数大,且次数多,那么损耗很大,若是引用,那么直接用地址该,损耗是较小的。(若用指针的地址,也是一样的,损耗较小,与引用差不多)
引用做参数的意义:
1.输出型参数,减少拷贝,提高效率
传值、传引用效率比较:
以值作为参数或者返回值类型,在传值和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时拷贝,因此用值作为参数或者返回值类型,效率是非常底下的,尤其是当参数或返回值类型非常大时,效率就更加底下
2.做返回值
这样做看似没问题,其实是没考虑到函数的栈帧问题。
ret是n的引用 他们是公用一个空间的。当count返回后,函数栈帧销毁,那么n的空间就会销毁,那么ret的空间也会销毁。
但是你仍然可以去访问这个ret 就造成了越界访问。
这里之所以第一次会正常打印,因为编译器还没有及时销毁函数栈帧,但是接下来几次,就是随机值了,因为ret的空间已经被销毁,归还给系统了,所以变成了随机值,也造成了越界访问
但是也有例外,当你把n的权限扩大,扩大成静态变量,不与函数栈帧销毁时一起销毁,就不会造成此类问题
可以看出,三次都是正常打印。
当用值返回时:
用值返回,中间是有一份临时变量,当此数多且多次返回时,会造成效率低下,而用引用返回时,时不会有这一份临时变量的,效率更高。
引用返回与值返回:
如果函数返回时,出了函数作用域,如果返回对象,还在(还没返还给系统)则可以使用引用返回,如果返回对象不在(已经返还给系统)就不能用引用返回,必须用值返回
在汇编中 他们的汇编指令其实是相同的
引用和指针的不同点:
1.引用在概念上定义一个变量的别名,指针存储一个变量地址。
2.引用在定义时必须初始化,而指针没有要求(但建议初始化)
3.引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时间指向任何一个同类型的实体
4.没有NULL引用,但有NULL指针
5.在sizeof中计算的含义不同
引用的结果是类型的大小
指针始终是地址空间所占字节个数 (4/8)
6.引用自加即实体增加1 指针自加即指针向后偏移一个类型的大小
7.有多级指针,但没有多级指针
8.访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9.引用比指针使用起来相对安全
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建议栈帧的开销,内联函数提升程序运行的效率
内联函数(inline)是C语言宏(define)升级过来的。
很多人会犯的错误 就是每个参数都要加括号 不然会出错,这样导致了C语言的宏不够好。
C语言宏的缺陷:C的宏不支持调试,并且容易出错
内联函数 只需要在函数的返回类型前+ inline就可以
但是在汇编中,无法查看编译器对inline展开 这里需要一些设置
inline的优点:debug支持调试,不容易写错,与普通函数写法相同
inline的特性:
1.inline是一种空间换时间的做法,省去调用函数额外开销(建立栈帧)但是代码很长(通常为10行,取决于编译器)或者有递归的函数不适应作为内联函数
2.inline对于编译器而言只是一个建议,编译器会自动优化,如果定义inline的函数很长或者递归函数等等,编译器优化时会忽略掉内联
3.inline不建议声明和定义分离,分离会导致链接错误,因为inline被展开,就没有函数地址了,链接就会找不到。(建议直接在.h(声明)内直接实现
自动推导赋值的类型
typeid 它是打印类型名 返回的是字符串
当然 也可以推导其他类型
auto的意义之一:变量名很长时,可以用auto自动推导
范围for
依次取 arr 中的数组 赋值给e 用auto自动判断
for循环后的括号由冒号“:”分为两部分 第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围
引用取arr的值赋值给e 所以e无法直接改变arr里的值。但可以用引用 改变
这里其实可以不用auto 可以自己指定类型 int 但是用auto更方便
auto不能作为函数形参类型 auto不能作为函数返回类型
auto不能作为数组类型 auto不能作为缺省参数
范围 for的使用条件
1.for循环迭代的范围必须是确定的
对于数组而言,就是数组中第一个元素和最后一个元素的范围:对于类而言,应该提供begin和end的方法,begin和end就算for循环迭代的范围
这里之所以错误,因为传参传的是地址 范围是不确定的,所以不能使用范围for
若本篇文章对您有帮助,希望能获得您的赞!
【Python 实战基础】如何绘制关系网格图展示8个节点间的关系
【VisionMaster 行业应用案例】第二讲 多相机定位引导应用
路透社:谷歌已停止与华为部分合作;联想否认断供华为PC;微软计划直供Linux内核;谷歌无人机快递Wing进军芬兰……...
视频增强论文Spatio-Temporal Transformer Network for Video Restoration阅读笔记
阿里p8大佬,总结的3~5年的软件测试职业规划+学习路线,行得通吗
报错ImportError: numpy.core.multiarray failed to import
A Survey on Graph Structure Learning: Progress and Opportunities