1.命名空间
1.1命名空间的功能
在c语言当中,如果创造两个同名的变量,一个是全局变量,一个是局部变量,那么调用的时候是会先调用局部变量的,在c++中,如果想要调用全局变量,就需要用到命名空间了

例如这样
同样的,命名空间也可以防止变量名和函数名冲突


这种情况,就可以在命名空间里定义变量,用来防止冲突

从本质上来说,命名空间是通过单独开了一个域来创建变量
在c++中,一共有着四种域,分别是函数局部域,全局域,命名空间域,类域
域实际上是通过编译时对函数,变量等进行隔离
此外,函数局部域和全局域还会影响变量的生命周期,命名空间域和类域则不会影响
命名空间只能够定义在全局,可以进行嵌套定义

在多个文件中定义的同名命名空间会被认为是同一个命名空间,不会冲突
c++标准库存放在了一个名叫std的命名空间
1.2命名空间的使用方法
命名空间有三种使用方法
1.指定命名空间访问(较推荐)

类似于这种,::就是访问命名空间的操作符
2.用using展开命名空间中指定的成员()

3.直接展开一个命名空间(不推荐,在日常编程中可以写,但在项目中不推荐)

2.c++的输入输出流
c++的输入输出流是类似于c语言中的printf/scanf函数的,这里介绍三个常用的:
- cin:类似于scanf
- cout:类似于printf
- endl:相当于输出了一个换行符,并且刷新了缓冲区
这三个函数都包含在std这个命名空间里。
与c语言不同的是,cout/cin不用像printf和scanf一样使用占位符,它可以自动识别变量的类型,十分方便。
<<、>>在c++中分别叫流插入运算符和流提取运算符,在c语言当中,它们是左移右移操作符。
这里复习一下左移右移的意思:

定义一个变量为a,下面是a的二进制
当对a进行左移1时,将a的二进制位整体往左移一位,在末位补上0
当对a进行右移1时,将a的二进制位整体往右移一位,在首位补上0
如下


有时候没有包含stdio.h时,使用printf/scanf编译器也不会报错,原因是在包含iostream时,间接包含了stdio.h。
3.缺省参数
缺省参数就像现实中的舔狗一样,当函数有实参时,就不需要缺省参数,当函数没有实参或者实参不完整时才需要缺省参数,所以说,做人不要做缺省参数(qwq)。
开个玩笑,简单来讲,缺省参数就是给函数的参数一个默认的值,当调用函数时没有给对应的实参时,就会默认使用缺省参数。
根据缺省的类型可以分为全缺省和半缺省:
全缺省指的是在调用函数时,一个实参都不给,如下:

半缺省指的是在调用函数时,给了部分实参:

在设置缺省参数时,要从右往左给缺省参数的值,不能跳跃给值;在给函数实参时,要从左往右给函数实参,也不能跳跃给值。
当函数声明和定义分离时,如果要给缺省参数,只能在函数声明时给。
4.函数重载
在c++中,同一作用域内是可以有同名函数的,但要求函数的参数要不一样,要么是类型不同,要么是个数不同:

需要注意的是,当返回类型不同时并不能算函数重载,因此不能够有同名函数:

可以看到,编译器也给出了报错。
5.引用
5.1概念和定义
引用相当于给变量起了一个别名,与指针不同的是,指针会创造额外的空间来储存地址,而引用不会。
5.2引用的特性
- 引用的时候必须初始化,这也是和指针不同的。
- 一个变量可以有多个引用。
- 一个引用只能引用一个对象。
- 一个引用也可以被引用。

因为b是a的引用,c是b的引用,相当于b和c都是a的别名,因此,更改c的同时,a和b都被改变了
5.3引用的使用

引用的主要作用是引用传参和引用做返回值,前者是为了改变引用的同时改变被引用对象的值(类似于传地址)
后者则是为了减少临时变量的创建和拷贝以提高效率
如上图所示,假如返回类型为int,那么在将值返回的过程中,会创建临时变量,导致效率变低,如果返回类型是int& ,则说明返回的是一个引用,并不会创建额外的变量
并且在特殊场景中,返回类型为引用还有特殊的作用,例如取栈顶元素的过程,如果用引用做返回类型,那么就可以直接更改栈顶元素,因为返回来的是栈顶元素的引用,改变它就相当于改变栈顶元素,十分方便
但返回类型为引用时要注意一个问题,假如想要引用的对象是在栈区上创建的,那么这个对象出了函数就会销毁,就会导致引用变成一个空引用(类似于空指针)
5.4.const引用
被const修饰的变量也可以被引用,只不过必须被const引用引用
而const引用既可以引用普通变量,也可以引用被const修饰的变量
本质上是权限的放大缩小问题

当原变量未被const修饰时,它的权限是较大的,因此它既可以被普通引用引用,也可以被const引用引用
当原变量被const修饰时,假如它要被普通引用引用,这是不行的,因为原变量不可以被更改,引用之后变成了可以被修改,使权限放大了,这是不行的
可以这样记,权限可以缩小不能放大
还有两种特殊情况,如下

这两个报错其实根本上是同一个原因
a+b在被c引用的过程中会创建一个临时变量,相当于这个临时变量被c给引用了,而临时变量具有常量性,必须在前面用const修饰
第二个也是类似的,e原本类型是double,当要被d引用时,因为d引用是int类型引用,因此在引用的过程中会发生类型转换,在类型转换的过程中同样也会创建临时变量,临时变量具有常量性,所以前面必须用const修饰
5.5引用和指针的区别
1.引用不会创建空间,指针会
2.引用必须初始化,指针可以不用初始化(建议初始化)
3.引用只能引用一个对象,指针可以改变它指向的对象
4.在使用sizeof时,指针的大小是取决于平台的类型的,32位平台4个字节,64位平台8个字节,引用则取决于引用对象的数据类型
5.引用可以直接访问对象,指针需要解引用才能访问
6.指针会经常出现空指针或野指针的情况,引用则不会
6.内联函数
内联函数和宏函数很像,内联函数会在编译的时候展开函数,宏函数则会在预处理的时候直接进行文本的替换,展开函数,可因为宏函数的使用很容易出现bug,所以c++中新增了内联函数来替代宏函数
接下来以Add函数为例,我们先写几个宏

上面这三种写法都是错的
1:第一种情况在特殊的情况下会发生错误,如下

2:第二种情况在遇到表达式的时候会出错,如下

这种情况下,因为&|的优先级较低,变量替换后会先进行加法的计算,无法达到想要的效果
3:第三种情况在遇到乘法时会出现错误,如下

本来应该输出15,却输出了11
综上所述,宏函数写的时候时长会出现一些小bug,因此我们可以改用内联函数
写法如下

还有一个很有意思的点,即使你加上了inline,如果编译器认为inline会导致消耗变多,那么它并不会展开函数,也就是说inline只是一个建议,如果编译器认为你的建议不合理,那么就不会听从你的建议
(tips:当遇到递归调用,或者调用的函数较大时就不会展开函数)
在debug模式下,内联函数是默认不会展开的
如果想要展开,参考下图

内联函数不建议定义和声明分离到两个文件,会导致链接错误,建议直接写到一个头文件
内联适用于频繁调用的短小函数
7.nullptr
nullptr和c语言中的NULL很像,但是由于NULL经常会被直接替换成0,所以c++中有了新的关键字nullptr,它只会隐式地转换为任意类型的空指针,并不会转换为0,因此可以避免想用指针时用到NULL的尴尬问题,所以在c++中,一般都采用nullptr
以上就是本篇文章的全部内容了,如果对你有帮助,可以点个赞支持一下,感谢各位的观看
TA 关注的仓库 - 陌染青云 (mo-ran-qingyun) - Gitee.com
这是我个人的gitee 仓库,账号上文章的代码都会发到仓库里,有兴趣可以看一下