18.inline 函数工作原理-灵析社区

菜鸟码转

1.内联函数的工作原理:

  • 内联函数不是在调用时发生控制转移关系,而是在编译阶段将函数体嵌入到每一个调用该函数的语句块中,编译器会将程序中出现内联函数的调用表达式用内联函数的函数体来替换。函数调用时,需要切换栈帧寄存器,同时栈中压入参数、返回值,然后进行跳转,这些都需要开销,而内联函数则可以不要这些开销,直接将内联函数中函数体直接插入或者替换到该函数调用点。
  • 普通函数是将程序执行转移到被调用函数所存放的内存地址,当函数执行完后,返回到执行此函数前的地方。转移操作需要保护现场,被调函数执行完后,再恢复现场,该过程需要较大的资源开销。
  • 虽然内联函数在调用时直接进行展开,但实际在编译后代码中存在内联函数的定义,可以供编译器进行调用。普通函数可以有指向它的函数指针,内敛函数也可以有指向它的函数指针。

2.内联函数的优缺点:

  • 内联函数具有以下优点:

不会产生函数调用开销。节省了调用函数时在堆栈上推送/弹出变量的开销。节省了函数返回调用的开销。当你内联一个函数时,你可以让编译器对函数体执行上下文特定的优化,其他优化可以通过考虑调用上下文和被调用上下文的流程来获得,而对于普通函数不会有这种优化。

  • 内联函数的缺点:

从内联函数中添加的变量会消耗额外的寄存器,在内联函数之后,如果要使用寄存器的变量数量增加,则可能会在寄存器变量资源利用方面产生开销。在函数调用点替换内联函数体时,函数使用的变量总数也会增加,用于存储变量的寄存器数量也会增加。因此,如果在函数内联变量数量急剧增加之后,它肯定会导致寄存器利用率的开销。

如果你使用太多的内联函数,那么二进制可执行文件的大小会很大,因为相同的代码重复。

过多的内联也会降低指令缓存命中率,从而降低从缓存内存到主内存的指令获取速度。

如果有人更改内联函数内的代码,内联函数可能会增加编译时间开销,那么所有调用位置都必须重新编译,因为编译器需要再次替换所有代码,否则它将继续使用旧功能.

内联函数可能会导致抖动,因为内联可能会增加二进制可执行文件的大小。内存抖动会导致计算机性能下降。

3.inline 函数的使用场景:

内联函数一般只适用于比较短小,处理较为简单的函数。内联只是对编译器的请求,而不是命令。编译器可以忽略内联请求。编译器可能不会在以下情况下执行内联:

如果函数包含循环(for, while, do-while);

如果一个函数包含静态变量;

如果一个函数是递归的;

如果函数返回类型不是 void,并且函数体中不存在 return 语句;

如果函数包含 switch 或 goto 语句;

4.内联可以去除函数只能定义一次的限制:

内联函数可以在程序中定义不止一次, 但是 inline 函数的定义在某个源文件中只能出现一次,而且在所有源文件中,其定义必须是完全相同的。一般情况下,我们可以在头文件中定义 inline 函数,所有 include 该头文件,如果修改了头文件中的 inline 函数时,使用了该头文件的所有源文件都必须重新编译。比如我们可以在定义以下两个文件包含相同的函数。

C++

// b.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

inline int min(int a, int b) {
    return a + b;
}

// a.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

inline int min(int a, int b) {
    return a + b;
}

int main() {
    int a = 10, b = 9;
    min(a, b);
    return 0;
}


阅读量:1438

点赞量:0

收藏量:0