1.对代码段封装的宏函数与函数
函数的封装涉及函数调用的创建形参,传递实参和开辟栈帧,执行函数体,返回返回变量,栈帧销毁,接收返回值。
宏函数的封装涉及代码替换,参数整体替换,在执行函数体(宏本质是宏替换,宏展开)
函数 | 宏函数 | |
开空间 | 开 | 不开(效率高) |
汇编指令复用 | 会 | 不会 |
类型识别 | 识别 | 不识别(不安全) |
可调试? | 可调试 | 不可调试(预处理阶段替换,编译时显示的原代码,不会显示过程,因为代码不同) |
计算顺序保护 | 不需要 | 需要 (宏参数不会先计算后传值,只会进行整体替换 所以参数加(),即(参数),(整体) ) |
代码量与使用次数 | 不变 | 随使用次数的增加而增加(会导致程序变大,传输慢且占用资源) |
由上面我们可以看出,函数较宏函数具有可调试,代码小,参数类型检验及不用管函数体代码的执行顺序等特点,完胜宏函数,这也是为什么我们很少用宏函数,但是函数也有其缺点,开空间消耗大,而宏函数则不然,我们考虑将二者结合起来以实现优势互补。
话虽如此,那么该怎实现呢?乃就是定义一种新的封装方法,它既有能完成参数类型识别,先求值后传值,可调试传参的函数的调用+代码替换的函数体执行方式——内联函数
然而代码替换会使得,代码量随使用次数而增加(具体要看:函数体的代码大小*调用次数),本质是汇编指令重复产生(宏展开,是将函数体所有的汇编指令在产生一次;不展开,则是会产生call命令,其他汇编命令都是复用之前的)内联函数同样有这个弊病,过多使用反而是用珍贵的空间换取有限的时间减短,所以在内联函数使用使用次数较多时会自动选用函数开空间的函数体执行方式。
2.内联函数的概念
通过选择性的改变函数体执行方式来实现函数性能效率的提升,应用在函数体小(10行内),使用次数多的函数(这才能合理利用空间,时间)
3.内联函数的定义,声明,调用
定义; inline关键字的使用
inline 返回类型 函数名 (参数列表) { 函数体 }
声明:声明与定义不分离(两者不会跨文件,哪怕在.h文件)
why:函数调用时候不同,放生在预处理时
如果定义声明是.cpp文件间,则在预处理时没有函数修饰名,没有占位符,在符号表中无对应的函数名,编译器找不到定义的地址。
如果是在.cpp与.h文件间,会有头文件展开和宏展开的冲突。
而在一个文件时,替换时定义存在。
由此看出内联函数本质替换,而非寻址找代码
4.内联函数的特性——占优补缺
1,占据函数的优势——类型检查,执行顺序固定,可调试(代码不变)
2,补充了函数的缺陷——有选择的展开不开空间
5.内联函数是否展开的条件
原则: 代码尽量小的同时多展开
看大小,一定要小
看次数,多次使用,不用递归(过大)
看版本,debug默认开空间(可修改),release默认展开
注:展开域后决定于编译器,他回一句函数体和使用次数的实际情况来决定
6.内联函数的应用场景
当我们要多使用一个简短的函数时,不妨加上online。
7.内联函数的意义
1,完全代替宏
2,优化简短(10行内)的非递归多次使用的函数