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

目录

引用

内联函数

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(声明)内直接实现 


auto关键字

自动推导赋值的类型

 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


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

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值