目录
前言
一、命名空间
二、输入与输出
三、缺省参数
四、函数重载
五、引用
六、内联函数
七、extern
八、auto
九、基于范围的for循环
十、指针空值nullptr
前言
C++是兼容C的,所以C
一、命名空间
命名冲突问题
起的变量名或函数名与库里的函数或变量相同,从而冲突了,如下图
在公司团队协作做项目时,两个人起的变量名或函数名冲突
解决办法:定义一个命名空间
利用关键字namesapce,来隔离其中的变量或函数
vs是该命名空间的名字
注意:该命名空间里的变量依然是全局的,与其没什么区别,只是被隔离其中,想使用时方式不同
命名空间中,既可以定义变量,也可以定义函数
命名空间可以嵌套
同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中
注意:一个命名空间就定义了一个新的作用域
命名空间使用
加命名空间名称及作用域限定符
命名空间名字 + 作用域限定符(::) + 变量或函数
这种方式使用比较麻烦,但是可以做到很好的隔离
使用using将命名空间中成员引入
将其频繁使用的变量或函数展开,无论是隔离,还是使用上,都比较好
使用using namespace 命名空间名称引入
如上图,此方法将其命名空间中的内容全部展开,但缺点是隔离失效了
如下图,就是将C++的标准库完全展开
二、输入与输出
输出:cout——流插入
无需再借助格式符,但是对于控制小数点位数不是很方便,所以此种情况建议使用printf
输入:cin——流提取
同样不需要格式符
endl——换行
三、缺省参数
概念:声明或定义函数时为函数的参数指定一个默认值
全缺省
即一个参数都不传
半缺省
即只传部分参数
不缺省
当没有传参时,就使用参数的默认值,当有传参时,则使用指定的实参
注意
半缺省只能从右至左缺省,不能间隔着给
缺省参数不能在函数声明和定义中同时出现
缺省参数必须是常量或者全局变量
四、函数重载
概念:在同一作用域中声明的几个功能相似的同名函数
函数重载有三种形式,参数类型,参数个数,参数顺序
注意:返回值类型不同不能算函数重载
参数类型不同
参数个数不同
参数顺序不同
注意:函数重载与缺省参数不能同时使用,因为在函数调用时可能会存在歧义,如下图
名字修饰规则
linux的函数名修饰规则
_Z+函数长度+函数名+类型首字母
如上图修饰后,应为_Z3facii
如上图修饰后,应为_Z3faci
C++是通过函数修饰规则来区分,只要参数不同,修饰出来的名字就不一样,就支持了重载
五、引用
概念:就是对同一事物起了个别名,比如张三是他姓名,而狗蛋是他小名,无论哪个都是代表他,只是称呼不同而已,如下图,b就是a的别名
类型& 引用变量名(对象名) = 引用实体
注意:引用类型必须和引用实体是同种类型的
引用特点
引用在定义时必须初始化
一个变量可以有多个引用
引用一旦引用一个实体,再不能引用其他实体
常引用
权限放大,这种情况会报错
权限不变,正常执行
权限缩小,正常执行
使用场景
做参数
如下图,下列两个函数构成函数重载,但在调用swap函数时会存在歧义
价值
提高效率
形参的修改,可以影响实参(输出型参数)
做返回值
如下图,函数返回时,是通过一个临时变量存储ret的值,再将其返回给c的,而不是直接将ret赋值给c的,因为如果是直接将ret赋值给c,在函数调用结束后就已经销毁了,这时就是非法访问
临时变量具有常性
如果ret比较小时(4/8byte),一般是是寄存器充当临时变量
如果ret比较大时,临时变量是建在调用Add函数的栈帧中,即main函数
如下图,就是直接返回c的引用,没有经过临时变量,因为被调用的函数的c是静态变量,不会随着函数调用结束而销毁
价值
提高效率
修改返回变量
结论:const Type & 常量 可以接收各种类型的对象,如下图
使用引用传参,如果不修改实参,那么建议使用const&
注意:如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回
引用与指针的区别
引用在语法概念就是一个别名,没有空间的;在底层实现上是有空间的
二者的不同点
引用在使用时必须初始化,而指针最好初始化,否则会是野指针
引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
没有NULL引用,但有NULL指针
在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数
引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
有多级指针,但是没有多级引用
访问实体方式不同,指针需要显式解引用,引用编译器自己处理
引用比指针使用起来相对更安全,因为指针存在NULL指针解引用、野指针问题等等
六、内联函数
C语言中有#define定义函数,而C++为了解决此种方法的缺点,引入了内联函数
概念:以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率,如下图
特性
inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数(10行以内适用)
inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联
inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到
建议:短小、频繁调用的函数建议定义成inline
七、extern "C"
告诉编译器,将该函数按照C语言规则来编译
extern这个关键字可以实现C程序调用C++的库,也能C++程序调用C的库
在VS2019中,以静态库为例
首先创建一个空项目,然后在属性页,在常规选项中,将下列改为静态库
在有主函数的项目中,在属性页的链接器的常规中,添加库目录,然后在输入中的附加依赖项中添加静态库,如下图
C++程序调用C的静态库
C程序调用C++的静态库
法一
法二
总结
C++程序调用C的库,在C++程序中加extern "C"
C程序调用C++的库,在C++库中加extern "C"
八、auto
在C++11中,auto可用于推导类型,如下图
typeid打印变量的类型
注意:使用auto定义变量时必须对其进行初始化
用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
当在同一行声明多个变量时,这些变量必须是相同的类型
auto不能作为函数的参数
auto不能直接用来声明数组
九、基于范围的for循环
在C++11中,对有范围的集合,for循环可修改为for(范围内用于迭代的变量 : 被迭代的范围),也被称为语法糖
上图是自动依次将数组a中的每个元素赋值给b,当然,上图中的auto也能改为int,也能通过b来调整值,如使b+1等等
注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环
for循环迭代的范围必须是确定的
对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围
如上图,因为形参a是指针,而不是数组名了,最后一个元素不能确定,所以不能这样使用for循环
十、指针空值nullptr
NULL实际是一个宏
NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量
注意:
在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的
在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同
为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr