内联函数在编译时进行展开,在调用点处产生一个函数体代码的拷贝。因此,对内联函数进行任何修改后,都需要对所有调用该函数的模块进行重新编译,否则它将会继续使用旧的函数。

如果想把一个函数定义为内联函数,则需要在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。

内联函数的作用:
引入内联函数的目的是为了解决程序中函数调用的效率问题,函数的调用会有函数栈帧的开辟和函数内资源回收处理时产生的开销。如果函数功能比较简单,如整数比较大小函数int Compare_Int(int a,int b){ return a-b;} ,此时函数体很小,而调用函数的开销却很大,调用这样的函数效率不会很高。如果我们使用宏定义的方式调用宏函数,效率是有了保证,可函数安全性就没有保证了。宏展开是在预编译阶段进行的,该阶段只是做简单的替换和展开工作,没有类型检查不安全。因此,内联函数的编译时在调用点展开的特性刚好可以解决这个问题。

提问:

  1. 内联函数什么时候展开?
    编译期展开(如果在预编译期展开不会检查类型)

  2. 内联函数一定会展开吗?
    inline是对编译器的一个建议,编译器会根据具体情况考虑是否处理。如递归函数不可以是内联函数。

    其中,内联函数在编译时(vs 2019):
    在debug中可以调试,会产生一个local符号,也会进行函数栈帧开辟之类的动作
    在realse版本中,不会产生符号和栈帧的开辟,会在调用点进行展开

内联函数、宏函数和普通函数比较:

inline函数 static函数 宏函数
符号 debug中产生local符号,realse中不产生符号 产生local符号 不产生符号
栈帧 debug中进行开辟栈帧等操作,realse直接在调用点展开(编译器) 进行栈指针操作 在调用点展开(预编译期)
调试 可以调试 可以调试 不可以调试
安全 有类型检查 有类型检查 没有类型检查

代码分析:对于求和函数sum()的分析。

#include <iostream>
using namespace std;#define SUM(a,b) {(a)+(b)}         // 宏函数int sum(int a, int b)             //普通函数     global符号
{/* 开销(形参开辟空间)push ebpmove ebp,espsub esp,0cch……*/return a + b;/* 开销(返回值的带出)mov eax,dword ptr[a]add eax,dword ptr[b]*/
}
/* 开销(回收函资源)
pop ……
mov esp,ebp
pop ebp
ret
*/inline int sum2(int a, int b) //内敛函数 不产生符号(realse)    debug产生local符号
{return a + b;
}inline int sum3(int a, int b); //声明在编译期产生符号,存在符号表中  *UND*static int sum4(int a, int b)  //静态函数  local
{return a + b;
}// 实现求和运算 -> Sun(int,int)
int main()
{int a = 10;int b = 20;// 方案一:调用函数实现求和int c = sum(a, b);                  //反汇编--->指令很多——效率低/*mov eax,dword ptr[b]push eaxmov eax,dword ptr[a]push eaxcall sum(0x……)add esp,8*/// 方案二:直接求和int d = a + b;                      //反汇编--->指令少——效率提升,但没有封装,不可以重复使用/*mov eax,dword ptr [a]add eax,dword ptr [b]mov dword ptr [d],eax*///  方案三:宏函数                  //效率提升,但不安全int f = SUM(a, b);/*优点:不存在 栈帧开辟,不存在参数的带入,不存在返回值的带出,不存在参数的清除缺点:不存在类型、安全检查,不可以调试*/// 方案四:内联函数int e = sum2(a, b);/*e = a + b;       //展开*/return 0;
}

引用:以下引用自博客 内联函数的声明和定义

inline函数的规则
  1. 一个函数可以自已调用自已,称为递归调用(后面讲到),含有递归调用的函数不能设置为inline

  2. 使用了复杂流程控制语句:循环语句和switch语句,无法设置为inline

  3. 由于inline增加体积的特性,所以建议inline函数内的代码应很短小。最好不超过5行。

  4. inline仅做为一种“请求”,特定的情况下,编译器将不理会inline关键字,而强制让函数成为普通函数。出现这种情况,编译器会给出警告消息。

  5. 在你调用一个内联函数之前,这个函数一定要在之前有声明或已定义为inline,如果在前面声明为普通函数,而在调用代码后面才定义为一个inline函数,程序可以通过编译,但该函数没有实现inline。比如下面代码片段:最终没有实现inline;

//函数一开始没有被声明为inline:
void foo();
//然后就有代码调用它:
foo();
//在调用后才有定义函数为inline:
inline void foo()
{......
}
  1. 为了调试方便,在程序处于调试阶段时,所有内联函数都不被实现

使用内联函数时应注意以下几个问题:

  1. 在一个文件中定义的内联函数不能在另一个文件中使用。它们通常放在头文件中共享
  2. 内联函数应该简洁,只有几个语句,如果语句较多,不适合于定义为内联函数
  3. 内联函数体中,不能有循环语句、if语句或switch语句,否则,函数定义时即使有inline关键字,编译器也会把该函数作为非内联函数处理。
  4. 内联函数要在函数被调用之前声明。关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用

C++ | 内联函数相关推荐

  1. 内联函数inline

    结论在文章末尾处! 在C++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数. 内联函数的处理方式是在函数的调用点直接代码展开.在计算机系 ...

  2. C语言的内联函数的作用

    关内联函数键字inline void myprintf(int a) { priintf("%d",a); } int main() { for(i=0;i<100;i++) ...

  3. Matlab编程与数据类型 -- 内联函数

    本微信图文详细介绍了Matlab中的内联函数.

  4. C++中虚函数可以是内联函数吗?

    1.需要注意的几点: 虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联. 内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因 ...

  5. C++中的内联函数inline

    1.Cpp中的内联函数 内联函数是通常与类一起使用.如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方.对内联函数进行任何修改,都需要重新编译函数的所有客户端,因 ...

  6. c语言函数参数类型检查,内联函数在编译时是否做参数类型检查?

    先说宏和函数的区别: 1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型. 2. 宏的参数替换是不经计算而直接处 ...

  7. c++学习笔记内联函数,函数重载,默认参数

    c++学习笔记内联函数,函数重载,默认参数 1 inline内联函数 C++中的const常量可以替代宏常数定义,如: const int A = 3;  #define A 3 C++中是否有解决 ...

  8. C6000系列DSP的内联函数

    在c中,为了解决一些频繁调用的小函数大量消耗栈空间或是叫栈内存的问题,特别的引入了inline修饰符,表示为内联函数数.栈空间就是指放置程序的局部数据也就是函数内数据的内存空间,在系统下,栈空间是有限 ...

  9. DSP编程技巧---C/C++与汇编语言的交互之-使用编译器的内联函数

    在C/C++与汇编语言混合编程的情况下,一般我们都会选择C/C++来实现所期待的功能.在我们用C/C++来实现某些位操作.数学运算等功能后,编译器会尽可能地把它们编译为一些已经高度优化的汇编函数(内联 ...

  10. C++对象模型9——临时对象的生命周期、模板及实例化分析、内联函数

    一.临时对象的生命周期 T c=a+b 假设T是一个类型,那么上述代码执行时,首先会产生一个临时对象用来存放a+b的结果(拷贝初始化临时对象),然后用该临时对象拷贝初始化c,最后临时对象被释放.如果开 ...

最新文章

  1. .ne中的控制器循环出来的数据如何显示在视图上_Web程序设计-ASP.NET MVC4数据库操作实例...
  2. Linux/Unix the definition of cpu-nice
  3. lstm代码_只需5行代码!LSTM时间序列建模以及预测
  4. 高清摄像头MIPI接口与ARM连接【转】
  5. FRR BGP协议分析10 -- 路由衰减
  6. JDC job obend
  7. 【哈佛大学:计算生物学 生物信息学】学习记录(一)
  8. 一步步打造自己的通用上拉加载布局
  9. 计算机发展趋势 网络化,计算机的发展趋势表现在多极化网络化等几个方面
  10. 不变初心数 (15 分) C语言
  11. JS获取当前时间的前几天、前几周、前几个月、前几年的时间
  12. AE效果:过时与抠像
  13. 易语言打开摄像头_api摄像头拍照源代码 调用API函数创建视频设备
  14. 《致盛夏的七封情书》 ------------ 第一篇《晨曦》
  15. python----scatter绘画散点图
  16. 用户登录界面的测试用例
  17. gthub获得star指南
  18. 网址铺吧网址导航程序按来路显示网址生成源码
  19. Jquery参考手册免费下载
  20. Debian中文环境配置及几种中文编码的探究

热门文章

  1. VUE中集成H5直播点播播放器LivePlayer过程
  2. 高通平台开发系列讲解(QMI篇)高通平台QMI介绍
  3. Java Web中动态网页开发基础重点总结
  4. Android 4学习(8):用户界面 - Fragment
  5. 如何优化帮助中心、知识库中的搜索功能?
  6. Office Web外接程序开发流程
  7. Python中秋赏月专用代码【源码好又多】
  8. OpenCV实现显示窗口大小可调整,imshow函数鼠标拖动
  9. maven生命周期和常用命令
  10. 【重识云原生】第四章云网络4.8.2.2节——OpenFlow协议详解