一、基础知识
1、C++编译流程
以Unix系统编译中间文件为说明:
.cpp—(编译预处理)—>.ii—(编译)—>.s—(汇编)—>.o—(ld,连接)—>.out
2、#include
作用于编译预处理阶段,将被include文件抄送在include所在位置,并会在相应位置写出调用栈,生成中间文件.ii,该中间文件可读
include文件加引号表示先从当前目录寻找索引,加尖括号表示从编译器指定根目录索引,Unix默认为"~//usr/include"目录
3、定义、声明、头文件
.h头文件中只应存放三种代码:
函数声明:没有大括号,形如void fun()
变量声明:extern 变量名
class、结构体定义
extern表示声明一个全局变量
声明只是提示编译器,存在这个东西,并没有定义出实体,不定义直接调用会报错。
4、标准头文件结构
#ifndef HEADER_FLAG
#define HEADER_FLAG
/*头文件*/
#endif
这是为了防止多次include同一个头文件时,每次都抄送到预编译文件中,造成文件过大、循环导入或者结构体定义重复以致报错(声明重复问题不大)。
5、默认参数
在声明中写默认参数,不在定义中给默认参数。
6、调用函数过程
本地变量进入堆栈(未必初始化)
函数参数进入堆栈
返回地址计入堆栈
返回值进入寄存器(运行函数)
pop掉参数
返回值进入堆栈(返回地址,所以要pop掉参数,堆栈先进后出)
7、内联函数
在编译阶段优化,省略上一小结中复杂的堆栈操作,效果如下,
汇编(伪)优化如下,
注意,inline 函数名实际是一个声明,而非定义所以不需要额外声明。实际上以空间换时间(编译会将函数插入调用位置),编译器如果发现函数递归或者过于巨大,可能会拒绝inline操作,函数较小可能被自动inline,建议就是小函数inline(2-3行),超过20行的就不要inline了。
相比于宏,inline可以做类型检查,给出debug提示,下图中C++会提示double的f(a)和%d不匹配,C会直接给出一个奇怪的值,
8、const
初始化之后不可修改,值得注意的是下图这种,指针和const,到底是地址(指针)还是地址中的内容(对象)是const
重点在于const和*的位置顺序,下述代码中2、3两句等价,
且const变量不能传给其他非const的指针(因为这样有可能造成修改),
函数和const
函数虚参加const表示函数内部不可修改该变量,对输入无要求
return const 对接收函数返回的类型无要求
class和const
const 对象,此时我们不能保证class方法是否修改成员变量,又不能限制函数不能使用(class就没有意义了)
const 对象 or 成员变量是const,要求成员变量必须有初始值,因为事后无法赋值
main文件(编译时可以感知类声明文件),类声明文件,类定义文件:声明、定义(两个位置都需要添加)函数时后面添加const关键字如,int fun() const。
下图运行结果为"f() const",
实际构成了重载,