文章目录
- 宏定义与内联函数
- 1 普通函数
- 2 内联函数(inline)
- 3 宏定义(#define)
- 4 宏定义与内联函数的区别
宏定义与内联函数
1 普通函数
任何一次函数调用,程序都得进行保存和恢复状态信息的动作,用数据结构的术语说就是进栈和退栈,还有内存分配的过程。
2 内联函数(inline)
函数只要声明为内联,就会建议编译器不把它编译成一次函数调用,而在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用的开销,提高效率。
- 内联标记
inline要跟类的声明写在一起,写在声明类的.h文件中,而不是写在实现类的.cpp文件中。 - 一般在类的声明中直接写函数体,就会被自动识别为内联函数。
- 内联函数一般用于函数体的代码比较简单的函数,如果内联函数过于复杂,编译器会自动的把这个内联函数转换成普通函数。(不能包含复杂的控制语句,例如while、switch语句,且不能递归调用)
内联函数只是一种编译机制,仅仅是建议编译器进行内联,而编译器是否内联不一定,有的编译器甚至不允许内联。
inline函数允许每个翻译单元 (.cpp) 都拥有一份完全相同的定义;链接器会把多份实例合并成唯一一份实体,不会报多重定义错误。
所有地方的定义必须完全一模一样。如果不同 cpp 里 inline 函数定义不一样,属于 UB 未定义行为。
内联函数本质上还是真正的函数,依然会在编译期进行完整类型、语法的安全检查。
3 宏定义(#define)
宏定义是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换。
宏定义不是函数,预处理器用复制宏代码的方式代替函数的调用,也省去了函数压栈退栈过程。
宏定义是纯粹的字符串替换,不经过编译器语法解析,不会在编译期进行类型、语法的安全检查。
4 宏定义与内联函数的区别
相同:
- 宏定义和内联函数使用的时候都是进行代码展开;
- 都能在性能上进行一定程度的优化。
区别:
安全检查
宏定义是没有类型、语法等安全检查的,在预编译阶段就进行替换,无论对还是错都是直接替换;
内联函数会在编译时进行安全检查,在编译阶段才在调用处展开。函数桟帧
宏定义没有函数栈帧,无法断点进入宏,调试困难;
内联函数是依然保留函数栈帧,有调试信息,可以调试。展开的时机
宏定义是在
预编译阶段的时候把所有的宏名替换;
内联函数则是在编译阶段把所有调用内联函数的地方把联函数插入。