因为 C++ 的很多东西还是从 C 语言中来的,所以可能这个地方相对总结的比较简单。第一篇是基础知识。
C++的总体知识大致分为五类:
- 算术类型
- 复合类型
- 函数使用
- 逻辑关系
- 内存空间
- 标准类库
一、算术类型
C++ 的基本类型只有两类:整数 和 浮点数。
- 整型有下面几类
short
,int
,long
,long long
,char
,wchar_t
,char16_t
,char32_t
- 浮点型有下面几类
float
,double
,long double
1.1 整形和浮点型
相应的整形宽度设置为:
short
至少16位int
至少与short
一样长long
至少32位,且至少与int
一样长long long
至少64位,且至少与long
一样长
wchar_t
用来处理无法用8位来表示的字符集,它的长度由系统的选择决定。char16_t
和char32_t
和wchar_t
一样是用来处理无法用8位来表示的字符集的。bool
是一种新的类型,任何非零数值可以被隐式转换为true
,0被隐式转换为false
。
1.2 算术运算符
算术运算符包含我们常用的加减乘除,另外还有一个取模。其中需要注意的知识点有:
自动转换,C++ 会自动执行很多的自动转换:
- 将一种算术类型的值赋给另一种算数类型时,C++将对值进行转换
- 表达式中包含不同类型的时候,C++将对值进行转换
- 将参数传递给函数的时候,C++将对值进行转换
- 较大的浮点型转换为较小的浮点型或整形的时候,如果超出目标类型的取值范围,结果是不确定的
- 较大的整形转换为较小的整形,超出目标类型的取值范围,通常只复制右边的字节
使用
{}
进行初始化称为列表初始化(list-initialization),列表初始化不允许缩窄,如将int
型赋值给char
型- 在计算表达式时,C++自动将
bool
,char
,short
的值转换为int
。 - 强制类型转换可以使用两种方式,还有四个强制类型转换符
dynamic_cast
,const_cast
,static_cast
,reinterpret_cast
,具体的介绍在这里不详细描述。- (typeName) value
- typeName (value)
二、复合类型
C++中的复合类型既包括 C 中的数组、字符串、结构体、共用体、枚举、指针,又包含新的类等。
2.1 数组
数组的初始化有以下规则
- 只有在定义数组的时候才可以使用初始化
- 初始化数组的时候,提供的值可以小于数组的元素数目
- 如果只对数组的一部分进行初始化,则其他部分初始化为0
- 如果初始化的时候没有标明数组的元素个数,则自动计算提供的值的数目为数组元素个数
- 可以使用列表初始化来初始化数组,此时可以省略等号,当列表为空时,自动把所有元素设为0
2.2 字符串
C++中的字符串有两种:C-风格字符串和 string
类。
- C-风格字符串以
\0
结尾 - 任何两个由空白分割的字符串会自动拼接成一个
- C-风格字符串和
string
对象都可以使用列表初始化 string
可以使用 + += 等运算符,并可以直接将一个string
对象赋给另一个string
对象。- 进行行读取的时候,C-风格字符串使用
cin.getline(str, 20)
,而string
类使用getling(cin, str)
;
字符串的输入:
cin
使用空白(空格、制表符和换行符)来确定字符串结束的位置。getline()
通过回车键来确定输入结尾但不保存并丢弃回车符。get()
带参数通过回车键来确定输入结尾,但将回车符留在输入队列中。get()
不带参数读取一个字符。- 混合输入数字和字符的时候,
<<
读取数字后会把回车留在输入队列中。
2.3 结构、共用体、枚举
- C++中结构声明定义了一种新的类型,使用时可以省略
struct
,但 C 中不行。 - C++允许指定占用特定位数的结构成员,可以使用没有名称的字段来提供间距。
- 可以将一个结构赋给另一个结构
- 枚举提供了一种创建符号常量的方式,可以替代
const
。 - 枚举没有算术运算符
- 枚举默认情况下第一个元素为0,后续累加
2.4 指针
- 使用
new
来分配内存 - 只能使用
delete
来释放使用new
分配的内存 - 使用
new
创建动态数组,需要使用delete[]
来释放 - 指针的其他使用方式和C指针一致
三、逻辑关系
和C一样,C++的逻辑关系也有循环和分支两种,其中的注意点有:
- C++允许在循环中定义变量,且变量只在循环内有效。
- 递增和递减使用前缀格式的效率更高
四、函数使用
创建自己的函数,需要处理三个方面:
- 提供函数定义
- 提供函数原型
- 调用函数
4.1 函数参数
- 数组(当且仅当)作为参数使用,和指针含义一样
const
尽可能多的使用- 使用数组名和超尾作为参数,来表示一个数组
4.2 函数指针
对于一个函数double pam(int)
相应的函数指针定义为 double (*pf)(int)
使用函数指针调用函数为 double ret = (*pf)(5)
或 double ret pf(5)
4.3 内联函数
内联函数运行速度稍快,但是占用内存较多
使用内联函数:
- 在函数声明前加
inline
- 在函数定义前加
inline
4.4 引用变量
引用变量是已定义变量的别名。
使用引用参数的原因:
- 能够修改函数中的数据对象
- 能够提高程序的运行速度
使用时需要注意以下要点:
- 必须在声明引用的同时初始化
- 使用
const
进行常量引用,避免在函数中修改原有信息 - 引用变量不能使用表达式传参
- 引用参数是
const
的时候,在下面的两种情况下,将生成临时变量- 实参的类型正确,但不是左值
- 实参的类型不正确,但可以转换成正确的类型
- 返回引用类型能够提高效率
- 不能返回指向临时变量的引用
- 引用返回值可以作为左值,而常规返回值不能作为左值
C++11允许右值引用(&&)
常见的函数参数的传递指导原则如下:使用传递的值,不修改数据对象的函数:
- 数据对象很小,使用值传递
- 对象是数组,使用指针,并声明为
const
- 对象较大,使用
const
引用或const
指针
对于修改数据对象的函数:
- 对象是常规数据,使用指针
- 对象是数组,使用指针
- 对象是结构,使用指针或引用
- 对象是类对象,使用引用
4.5 默认参数
默认参数是指当函数调用中省略了实参时自动使用的一个值。需要注意的点为:
- 必须在原型中将可能的默认参数告知程序
- 必须从右向左添加默认值
4.6 函数重载
函数重载指可以有多个同名的函数,可以通过函数重载设计一系列的函数,他们完成相同的工作,但是使用不同的参数列表。
- 重载引用参数时的最佳匹配:
void function(double & arg)
匹配:
可修改的左值参数(如 double变量),同时也是最优匹配void function(const double & arg)
匹配:- 可修改的左值参数(如 double变量),
- 不可修改的左值参数(如const double常量),最佳匹配
- 右值参数(如 double + double),
coid function(double && arg)
匹配:
右值参数(如 double + double),同时也是最优匹配
4.7 函数模板
函数模板是通用的函数描述,它们使用泛型来定义函数,其中的泛型可以使用具体的类型替换。
建立函数模板的方式为:
- 显式具体化
- 对于给定的函数名,可以有非模板函数、模板函数、和显式具体化函数以及它们的重载版本
- 显式具体化的原型和定义应以
template<>
开头,并通过名称来指定类型 - 具体化优先于常规模板。
- 显式实例化:
- 显式实例化命令编译器创建特定的实例
- 显式实例化不能和显式具体化共存
- 显式实例化可以将参数强制转换为相应的类型
相应的代码示例为:
编译器选择函数版本的流程为:
- 创建候选列表
所有函数名相同的模板和函数 - 创建可行函数列表
所有参数匹配的函数 - 选择最佳函数
- 完全匹配 常规函数优先于模板
- 提升转换 char -> int float -> double
- 标准转换 int -> char double -> float
- 定义转换
针对无法确定的参数类型,C++11定义了关键字 decltype
- 使用方法为:
decltype (ecpression) var
ecpression
为标识符
var类型为标识符类型ecpression
为函数调用
var类型为函数返回值类型ecpression
为左值
var类型为指向类型的引用类型ecpression
为什么都不是
var类型为experssion的类型
同时针对返回值的类型,C++新增了后置返回类型auto function(int a) ->double;
五、内存空间
5.1 文件结构
程序可以分为三个部分:
- 头文件:包含结构声明和使用这些结构的函数的原型,主要包括:
- 函数原型
- 符号常量
- 结构声明
- 类声明
- 模板声明
- 内联函数
- 源代码文件:包含与结构相关的函数的代码
- 实现相关函数代码
- 源代码文件:包含调用与结构相关的函数的代码
- 业务逻辑调用相关函数代码
5.2 存储持续性
C++使用三种不同的方式来存储数据:
- 自动存储
- 存储时间:函数存在时
- 作用域为:局部
- 链接性为:无
- 内存区域:栈(后进先出)
- 静态存储
- 存储时间:整个程序运行时间
- 作用域为:局部或全局
- 链接性为:三种
- 外部链接性——全局变量,可以在一个文件中定义全局变量,其他文件使用extern声明
- 内部链接性——使用static修饰的全局变量
- 无链接性——使用static修饰的局部变量
- 内存区域:静态区域
- 动态存储
- 存储时间:new 分配的内存持续存在直至使用delete删除
- 作用域为:使用地址均可以访问
- 链接性为:使用地址访问
- 内存区域:堆
- 线程存储(C++11)
- 存储时间为线程周期