内联函数(inline)的内存原理 --- 拓展普通函数和宏的对比

张开发
2026/4/17 8:19:18 15 分钟阅读

分享文章

内联函数(inline)的内存原理 --- 拓展普通函数和宏的对比
1普通函数调用流程栈的使用假设有一个普通函数void Print() { int x 10; std::cout x; } int main() { Print(); }调用过程CPU 和栈视角调用Print()CPU 执行call Print当前栈帧main 的栈保存返回地址CPU 跳到Print的代码段执行创建Print的栈帧栈顶分配局部变量空间int x 10保存必要的寄存器、返回地址等函数体执行打印 x函数返回弹出栈帧恢复寄存器用栈中保存的返回地址跳回 main✅ 栈的特点每个函数调用都会分配自己的栈帧函数逻辑代码→ 固定在代码段调用时的栈帧→ 为函数的局部变量、返回地址、寄存器开辟临时空间函数执行逻辑在栈上运行结束后释放空间内联函数→ 减少栈帧创建局部变量在调用函数栈帧宏定义→ 文本替换直接在调用点执行也在调用函数栈帧2 内联函数的调用流程假设inline void Print() { int x 10; std::cout x; } int main() { Print(); }调用过程调用点直接展开函数体编译器把函数内容复制到调用点int main() {int x 10;std::cout x;}栈的变化没有新的栈帧分配变量x直接在 main 的栈帧上分配不用压返回地址不用跳转CPU 执行顺序就像你在 main 里直接写了int x 10; std::cout x;✅ 栈的特点没有独立栈帧局部变量在调用函数的栈帧里减少了压栈、跳转、返回的开销3宏定义#define和内联函数的表面相似#define SQUARE(x) ((x)*(x))使用时int a 5;int b SQUARE(a); // 编译器预处理时替换成 ((a)*(a))✅ 表面相似点都在调用处展开没有函数调用开销适合小功能频繁调用也不会压栈4宏定义的本质预处理阶段宏在编译前就被展开预处理器阶段编译器根本没有“看到函数”它只是文本替换b SQUARE(a); // 预处理后b ((a)*(a));内存上根本没有函数体不会有函数调用也没有inline之类的优化问题没有类型检查、可能有副作用总结对比特性普通函数内联函数栈帧独立栈帧不分配独立栈帧局部变量在调用点栈帧里返回地址压栈 ret无需压栈CPU 跳转call → 执行 → ret直接顺序执行展开代码局部变量在函数栈帧在调用函数栈帧这是图片对比外加宏。直接全部搞懂

更多文章