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

 更新时间:2022年04月21日 15:30:20   作者:清风自在 流水潺潺  
为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数

一、常量与宏回顾

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++内联函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解C++右值引用

    详解C++右值引用

    很多初学者都感觉右值引用晦涩难懂,其实不然。右值引用只不过是一种新的 C++ 语法,真正理解起来有难度的是基于右值引用引申出的2种 C++ 编程技巧,分别为移动语义和完美转发。本节给读者讲解什么是右值引用以及它的基本用法。
    2021-06-06
  • C++ 中的Swap函数写法汇总

    C++ 中的Swap函数写法汇总

    这篇文章主要介绍了C++ 中的Swap函数写法汇总,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-02-02
  • C++中模板和STL介绍详解

    C++中模板和STL介绍详解

    今天小编就为大家分享一篇关于C++模板和STL的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2021-09-09
  • 在编程语言中怎样定义队列及其使用(C++)

    在编程语言中怎样定义队列及其使用(C++)

    这篇文章主要介绍了在编程语言中怎样定义队列,本文主要根据c++来介绍,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • C语言编程银行ATM存取款系统实现源码

    C语言编程银行ATM存取款系统实现源码

    这篇文章主要为大家介绍了C语言编程银行ATM存取款系统实现的源码示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • STL中的string你了解吗

    STL中的string你了解吗

    这篇文章主要为大家详细介绍了STL中的string,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • C++使用expected实现优雅的错误处理

    C++使用expected实现优雅的错误处理

    C++ 中提供了很多中方式进行错误处理。无论是通过抛异常还是通过错误码,标准库都提供相应的调用,今天本文为大家介绍的是使用expected进行错误处理,感兴趣的可以了解一下
    2023-06-06
  • C++迭代器介绍(iterator、const_iterator、reverse_interator、const_reverse_interator)

    C++迭代器介绍(iterator、const_iterator、reverse_interator、const_rev

    这篇文章主要介绍了C++迭代器介绍(iterator、const_iterator、reverse_interator、const_reverse_interator),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • C语言实现房屋管理系统

    C语言实现房屋管理系统

    这篇文章主要为大家详细介绍了C语言实现房屋管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • C语言基于哈希表实现通讯录

    C语言基于哈希表实现通讯录

    这篇文章主要为大家详细介绍了C语言基于哈希表实现通讯录,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02

最新评论