【C++初阶】C++入门(下)

【C++初阶】C++入门(下)

🥕个人主页:开敲🍉

🥕所属专栏:C++🥭

🌼文章目录🌼

[6. 引用](#6. 引用)

[6.1 引用的概念](#6.1 引用的概念)

[6.2 引用特性](#6.2 引用特性)

[6.3 常引用](#6.3 常引用)

[6.4 使用场景](#6.4 使用场景)

[6.5 传值、传引用效率比较](#6.5 传值、传引用效率比较)

[6.6 引用和指针的区别](#6.6 引用和指针的区别)

[7. 内联函数](#7. 内联函数)

[7.1 内联函数的概念](#7.1 内联函数的概念)

[7.2 特性](#7.2 特性)

[8. 指针空值nullptr](#8. 指针空值nullptr)

6. 引用
6.1 引用的概念

引用不是定义一个新的变量,而是给一个已有的变量取别名,因此引用并不会开辟额外的空间,它跟它引用的变量共用一块空间。举个简单的例子:有个人名字叫张小明,在家里他爸妈给他取了一个小名叫明明,在学校同学们给他取了个名字叫小明,这里的明明和小明都可以理解为张小明的引用,它们所指向的对象都是张小明。

引用:类型 & 引用变量名 = 引用实体:

因为pa就是a,所以改变pa的值自然也就会改变a的值,因为操作pa就是在操作a:

**注意:**引用类型必须和引用对象是相同类型的!

6.2 引用特性

① 引动在定义时必须初始化,换句话说,引用必须指向一个对象,不能空引用

② 一个变量可以有多个引用,这点也很好理解,就像上面的张小明,在家里他爸妈叫他明明,在学校同学叫他小明:

③ 引用一旦指向了某个对象,则不能再更改引用的对象

6.3 常引用

权限放大:

由此可以知道权限放大是错误的,不合法的。

权限缩小:

由此可以知道权限缩小是合法的。

6.4 使用场景

① 做参数

在过去我们学习C语言时,想要将两个变量的值进行交换,我们写出的交换函数是这样的:

会不会觉得这样挺麻烦的,又要进行取地址操作&,又要进行解引用操作。

现在,我们学习了引用之后,我们就可以这样写:

能够这样写的原理就是上面说的,引用是对一个变量取别名,对这个别名的操作就是对变量本身的操作。

② 做返回值

6.5 传值、传引用效率比较

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

6.6 引用和指针的区别

引用是变量的一个别名,并不会开辟额外的空间,它和它引用的对象共用一块空间 ,对引用的操作就是对变量的操作,属于直接操作而指针是一块地址,它保存所指向对象的地址 ,因此指针开辟了额外的空间,对变量操作需要对指针解引用,因此属于间接操作引用在定义时必须初始化,而指针初不初始化都行不能出现空引用,可以出现空指针在sizeof中引用的大小就是所指向对象类型的大小,而指针始终为地址所占的空间大小(32位平台下为4个字节);

总结:

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

② 引用在定义时必须初始化,指针可以不初始化

③ 引用在指向了一个对象后不能再更改,而指针可以随便指向任何同一类型的对象

④ 不能出现空引用,可以出现空指针

⑤ 在sizeof中的含义不同:引用为指向对象类型的大小,指针固定为地址的大小(32位平台下为4个字节)

⑥ 对引用的操作就是对变量的直接操作,指针对变量操作需要解引用,属于间接操作

⑦****引用比指针使用起来相对更加安全

7. 内联函数
7.1 内联函数的概念

inline 修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方将其展开(不是一定的,这取决于编译器是否将其看作内联函数),没有函数调用建立的栈帧开销,因此内联函数提升了运行的效率。

如上图,没有使用内联函数时,反汇编中会有一句call指令,这说明编译器为这个函数开辟了一块栈帧,产生了空间的消耗。

如上图,使用内联函数后,编译器会将内联函数展开,因此没有了栈帧的创建。

7.2 特性

① inline 是一种以空间换时间 的做法,如果编译器将函数当作内联函数处理,在编译阶段,编译器会将内联函数展开缺陷: 可能会使代码量变大;**优点:**少了栈帧的创建,提高了运行效率。

inline 对于编译器来说只是一种建议,编译器是否会将其看作是内联函数取决于编译器本身,不同的编译器判断不一样。一般:当函数规模较小、非递归、函数频繁调用 时可以采用inline修饰,否则编译器可能不会将其看作为内联函数。下图为《C++ Prime》第五版对inline的建议:

inline不建议声明和定义分离,如果将inline的声明和定义分离会导致链接错误。因为当inline被展开后就没有了地址(没有开辟栈帧),链接时就找不到它。

8. 指针空值nullptr

在良好的C/C++编程习惯中,声明一个变量时最好给该变量一个合适的初始值,否则可能会出现

不可预料的错误,比如未初始化的指针。如果一个指针没有合法的指向,我们基本都是按照如下

方式对其进行初始化:

NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:

可以看到,在C++中,NULL为常量0;在C语言中,NULL为void*类型的常量。但是无论是哪种形式,在使用NULL时都不可避免会遇到一些麻烦,比如:

可以看到,func(NULL)的调用初衷是想调用第二个func,但是却调用了第一个,这就产生了歧义。

在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器

默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void

*)0。

因此在C++中,我们最好使用nullptr关键字来替代NULL。nullptr是专门用于指针类型的指针,而NULL即能代表常量0,又能代表(void*)类型的常量,出现歧义。

注意:

① 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为关键字引入的。

② 在C++11中,sizeof(nullptr)与sizeof((void*)0)所占字节大小相同。

③ 为了提高代码的健壮性,在后续表示指针空指时最好都使用nullptr。

创作不易,点个赞呗,蟹蟹啦~

相关推荐
老猿讲编程10 分钟前
一个例子来说明Ada语言的实时性支持
开发语言·ada
UestcXiye1 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
Chrikk1 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*1 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue1 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man1 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
霁月风2 小时前
设计模式——适配器模式
c++·适配器模式
萧鼎2 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸3 小时前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农3 小时前
Python 继承、多态、封装、抽象
开发语言·python