宏和inline函数的区别
1、 宏是编译阶段处理的,纯粹是字符串替换(坑确实很多,尤其是在表达式替换的时候),没有任何的类型检查等,十分的不安全;而 inline 函数的处理是发生在编译阶段的,有完整的语句类型检查,比宏更安全
2、 宏是无法调试的, inline 函数在 debug 版本下和普通函数一样,出了问题很方便进行断点调试,定位问题
3、 大量的宏很不方便去阅读源码, inline 函数和普通函数一样,结构模块化清晰,方便阅读代码
4、 用宏来代替函数定义,替换后还是一个正常的函数调用,有函数调用开销(栈帧开辟和回退);而inline函数是在编译时期,在函数调用点把函数的代码直接展开,省去了函数调用的开销,代码运行效率高
内联函数和普通函数的区别
普通函数的调用在汇编上有标准的 push 压实参指令,然后 call 指令调用函数,给函数开辟栈帧,函数运行完成,有函数退出栈帧的过程;而 inline 内联函数是在编译阶段,在函数的调用点将函数的代码展开,省略了函数栈帧开辟回退的调用开销,效率比较高!
内联函数和static修饰的函数的区别
1.static修饰的函数在调用时有函数调用开销(栈帧开辟和回退);而用 inline 函数是在编译时期,在函数调用点把函数的代码直接展开,省却了函数调用的开销,代码运行效率高
2.inline函数和static修饰的函数都会导致该函数本文件可见,不过原因不同。inline函数是因为在编译时期,在函数调用点把函数的代码直接展开,而static修饰的函数时直接修改了属性从global到local,导致本文件可见
inline函数注意事项:
1.inline函数的实现一般写在头文件中,如果定义写在头文件实现写在源文件会出现符号解析错误
2.inline函数只在Release版本生效,Debug版本还会处理为一个普通的函数,即有开栈清栈开销
3.inline函数只是给编译器的一个建议,不是所有的inline函数编译器都会处理为内联函数,例如递归、循环、switch一定不会处理为inline函数,因为编译器无法知道递归的次数,就无法确定展开多少次
4.inline函数是基于实现的,不是基于声明的,也就是说inline关键字不能写在定义点,要写到实现点,写在定义点一定不会展开
5.inline函数是以代码膨胀为代价,以空间换时间。如果开栈开销>执行开销,设为inline,相反则不设inline
问题:内联函数为什么要在编译期展开?
不在预编译期展开的原因:预编译期不会进行类型检查,如果在预编译期展开就无法进行类型检查,就和宏一样;
不在链接阶段展开的原因:因为在链接时,指令都已生成完成,在此时展开没有什么用。