C++深入分析内联函数的使用

目录
  • 一、常量与宏回顾
  • 二、内联函数
  • 三、内联函数使用注意事项
  • 四、小结

一、常量与宏回顾

C++中的const常量可以替代宏常数定义,如︰

但是C++中是否有解决方替代宏代码片段呢?这里就要引入内联函数。

二、内联函数

  • C++中推荐使用内联函数替代宏代码片段
  • C++中使用 inline 关键字声明内联函数

内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求

  • C++编译器可以将一个函数进行内联编译
  • 被C++编译器内联编译的函数叫做内联函数
  • C++编译器直接将函数体插入函数调用的地方
  • 内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)

C++编译器不一定满足函数的内联请求

下面先看一段宏定义的代码:

#include <stdio.h>
#define FUNC(a, b) ((a) < (b) ? (a) : (b))
inline int func(int a, int b)
{
    return a < b ? a : b;
}
int main(int argc, char *argv[])
{
    int a = 1;
    int b = 3;
    int c = FUNC(++a, b);
    printf("a = %d\n", a);
    printf("b = %d\n", b);
    printf("c = %d\n", c);
    return 0;
}

下面为输出结果,c =FUNC(++a, b),等价于 c =((++a) < (b) ? (++a) : (b)),先执行(++a) < (b),得到 a =,2,b = 3,由于 ++a 比 b 小,所以输出 ++a,这个时候 a = 3,所以 c 也等于 3。

如果使用内联函数,

#include <stdio.h>
#define FUNC(a, b) ((a) < (b) ? (a) : (b))
inline int func(int a, int b)
{
    return a < b ? a : b;
}
int main(int argc, char *argv[])
{
    int a = 1;
    int b = 3;
    int c = func(++a, b);
    printf("a = %d\n", a);
    printf("b = %d\n", b);
    printf("c = %d\n", c);
    return 0;
}

输出结果如下:

下面在 VS2012 中看一下反汇编的代码,看一看内联有没有成功。可以看到 func 函数被调用,而不是直接扩展到被调用的地方,内联没有成功。inline 这个关键字仅仅是请求将函数内联,但是不一定会成功。

为了让编译器允许对内联的请求,可以对编译器进行一些配置,如下图

配置好以后,在 int c = func(++a, b); 前面打个断点,开始跑代码,但是我跑的时候报错了。

这个时候,进行下面配置,那个错误就解决了。

这个时候在进行反汇编,如下图所示,可以看到调用函数的汇编代码没有了,表示内联成功了。

  • 内联函数具有普通函数的特征(参数检查,返回类型等)
  • 函数的内联请求可能被编译器拒绝
  • 函数被内联编译后,函数体直接扩展到调用的地方

宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程,因此可能出现副作用。

现代C++编译器能够进行编译优化,一些函数即使没有inline声明,也可能被内联编译

一些现代C++编译器提供了扩展语法,能够对函数进行强制内联,如︰

  • g++ : _attribute__((always_inline)) 属性
  • MSVC : _forceinline

三、内联函数使用注意事项

C++中 inline 内联编译的限制:

  • 不能存在任何形式的循环语句
  • 不能存在过多的条件判断语句
  • 函数体不能过于庞大
  • 不能对函数进行取址操作
  • 不能对函数进行取址操作

四、小结

  • C++中可以通过 inline 声明内联函数
  • 编译器直接将内联函数体扩展到函数调用的地方
  • inline 只是一种请求,编译器不一定允许这种请求
  • 内联函数省去了函数调用时压栈,跳转和返回的开销

到此这篇关于C++深入分析内联函数的使用的文章就介绍到这了,更多相关C++内联函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++内联函数详情

    内联函数是C++当中为了提高程序运行效率的设计,老实讲我没有在其他语言当中看到类似的设计.它和常规函数之间的主要区别不在于编写的方式,而是在于C++编译器会将内联函数组合到程序当中执行. 要解释这个过程会稍稍有些复杂,我们需要从编译的过程说起.对于编译型语言而言,编译器做的事情是把人类写出来人能读懂的代码翻译成机器能够识别.执行的机器语言,一般是一串十六进制的指令.随后计算机逐步执行这些指令,完成我们想要的功能. 当我们调用函数时,其实本质上是指令跳转,先记录下当前运行的指令位置,跳转到函数所在

  • c++内联函数(inline)使用详解

    介绍内联函数之前,有必要介绍一下预处理宏.内联函数的功能和预处理宏的功能相似.相信大家都用过预处理宏,我们会经常定义一些宏,如 复制代码 代码如下: #define TABLE_COMP(x) ((x)>0?(x):0) 就定义了一个宏. 为什么要使用宏呢?因为函数的调用必须要将程序执行的顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方.这种转移操作要求在转去执行前要保存现场并记忆执行的地址,转回后要恢复现场,并按原来保存地址继续执行.因此,函数调

  • 深入理解C++内联函数

    目录 内联函数的概念 内联函数和宏 内联函数的特性 总结 内联函数的概念 以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数的使用可以提升程序的运行效率. 举个例子: 在C++中我们通常定义以下函数来求两个整数的最大值: 代码如下: int max(int a, int b) { return a > b ? a : b; } 为这么一个小的操作定义一个函数的好处有: 阅读和理解函数 max 的调用,要比读一条等价的条件表达式并解释它

  • C++深入分析内联函数的使用

    目录 一.常量与宏回顾 二.内联函数 三.内联函数使用注意事项 四.小结 一.常量与宏回顾 C++中的const常量可以替代宏常数定义,如︰ 但是C++中是否有解决方替代宏代码片段呢?这里就要引入内联函数. 二.内联函数 C++中推荐使用内联函数替代宏代码片段 C++中使用 inline 关键字声明内联函数 内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求 C++编译器可以将一个函数进行内联编译 被C++编译器内联编译的函数叫做内联函数 C++编译器直接将函

  • 深入探讨:宏、内联函数与普通函数的区别

    内联函数的执行过程与带参数宏定义很相似,但参数的处理不同.带参数的宏定义并不对参数进行运算,而是直接替换:内联函数首先是函数,这就意味着函数的很多性质都适用于内联函数,即内联函数先把参数表达式进行运算求值,然后把表达式的值传递给形式参数.    内联函数与带参数宏定义的另一个区别是,内联函数的参数类型和返回值类型在声明中都有明确的指定:而带参数宏定义的参数没有类型的概念,只有在宏展开以后,才由编译器检查语法,这就存在很多的安全隐患.    使用内联函数时,应注意以下问题:    1)内联函数的定

  • C++编程中队内联函数的理解和使用

    函数调用过程 c++经过编译生成可执行程序文件exe,存放在外存储器中.程序启动,系统从外存储器中将可执行文件装载到内存中,从入口地址(main函数起始处)开始执行.程序执行中遇到了对其他函数的调用,就暂停当前函数的执行,并保存下一条指令的地址作为从被调函数返回后继续执行的入口点,保存现场.然后转到被调函数的入口地址执行被调函数.遇到return语句或者被调函数结束后,恢复先前保存的现场,从先前保存的返回地址处继续执行主调函数的其余部分. 内联函数 函数调用需要进行现场保护,以便在函数调用之后继

  • Kotlin 内联函数详解及实例

    Kotlin 内联函数详解及实例 概述 在说内联函数之前,先说说函数的调用过程. 调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方.这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行.也就是通常说的压栈和出栈.因此,函数调用要有一定的时间和空间方面的开销.那么对于那些函数体代码不是很大,又频繁调用的函数来说,这个时间和空间的消耗会很大. 那怎么解决这个性能消耗问题呢,这个时候

  • 浅谈内联函数与宏定义的区别详解

    用内联取代宏:1.内联函数在运行时可调试,而宏定义不可以;2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会: 3.内联函数可以访问类的成员变量,宏定义则不能: 4.在类中声明同时定义的成员函数,自动转化为内联函数.文章(一)内联函数与宏定义 在C中,常用预处理语句#define来代替一个函数定义.例如: #define MAX(a,b) ((a)>(b)?(a):(b)) 该语句使得程序中每个出现MAX(a,b)函数调用的地方都被宏定义中后面的表达式((a)

  • 内联函数inline与宏定义深入解析

    内联函数的优越性:一:inline定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换(像宏定义一样展开),没有了调用的开销,效率很高.二:类的内敛函数是一个真正的函数.三:使用内联函数inline可以完全取代表达式形式的宏定义. 例子: 复制代码 代码如下: Class A{public:int readTest(){return nTest:}void setTest(int i);};inline void A::setTest(int i){nTest=i;}; 说明:类A

  • C语言中的内联函数(inline)与宏定义(#define)详细解析

    先简明扼要,说下关键:1.内联函数在可读性方面与函数是相同的,而在编译时是将函数直接嵌入调用程序的主体,省去了调用/返回指令,这样在运行时速度更快. 2.内联函数可以调试,而宏定义是不可以调试的.内联函数与宏本质上是两个不同的概念如果程序编写者对于既要求快速,又要求可读的情况下,则应该将函数冠以inline.下面详细介绍一下探讨一下内联函数与宏定义. 一.内联函数是什么?内联函数是代码被插入到调用者代码处的函数.如同 #define 宏(但并不等同,原因见下文),内联函数通过避免被调用的开销来提

  • 详解C++中的内联函数和函数重载

    内联函数(内嵌函数,内置函数) 调用函数时需要一定的时间和空间的开销.C++提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开.这种在函数调用处直接嵌入函数体的函数称为内联函数(inline function),又称内嵌函数或内嵌函数. 指定内联函数的方法很简单,只需要在定义函数时增加 inline 关键字. 注意:是在函数定义时增加 inline 关键字,而不是在函数声明时.在函数声明时增加 inline 关键虽然没有错误,但是也没有任何效果 inline 关键

  • c++中的内联函数inline用法实例

    问题描述:类中成员函数缺省默认是内联的,如果在类定义时就在类内给出函数定义,那当然最好.如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上 inline,否则就认为不是内联的.内联函数的inline要加在函数前面,不可以加在声明前面. class A { public:void Foo(int x, int y) { } // 自动地成为内联函数 } //正确写法: // 头文件 class A { public: void Foo(int x, int y); } // 定义文

随机推荐