C++命名空间与引用全解析

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引用的特性

  1. 引用的时候必须初始化,这也是和指针不同的。
  2. 一个变量可以有多个引用。
  3. 一个引用只能引用一个对象。
  4. 一个引用也可以被引用。

因为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 仓库,账号上文章的代码都会发到仓库里,有兴趣可以看一下

相关推荐
用户7624117567051 小时前
第十五章 人工智能基础
c++
yangmu32032 小时前
编程语言发展简史:从机器指令到智能协作
开发语言
爱写Bug的浮游4 小时前
unique_ptr 零开销的真相与边界
c++·facebook
Pniubi4 小时前
Java为什么要分堆和栈
java·开发语言
xiaoye-duck4 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(下):流式响应实现和测试
网络·c++·语言模型·chatgpt
小小晓.5 小时前
Qt 对话框、QLineEdit 与布局管理实战详解
开发语言·qt
炸薯条!5 小时前
博客系统测试报告
开发语言·lua
Evand J6 小时前
【MATLAB例程12】永磁同步电机基于增广无迹卡尔曼滤波的未知负载转矩在线观测
开发语言·matlab
落樱弥城6 小时前
Perf 逐步探查性能缺口并优化
c++·性能优化