当前位置: 首页 > news >正文

C++内联函数inline

在 C++ 中,inline 关键字用于提示编译器将一个函数的调用代码替换为函数的主体,从而避免函数调用的开销(例如参数传递、堆栈管理等)。简言之,inline 函数的主要目的是减少函数调用的开销,提高性能,尤其是对于那些频繁调用的小函数。

inline 关键字的作用和使用

  1. 函数内联展开: 当函数被声明为 inline 时,编译器会尝试将该函数的调用替换为函数体的实际代码。这叫做“内联展开”。这种展开可以避免函数调用的开销,但是并不总是有效果——编译器可以根据实际情况决定是否展开。
  2. 减少函数调用开销: 一般来说,函数调用有一定的性能开销,尤其是当函数被频繁调用时。内联函数通过直接展开函数体,可以减少调用和返回带来的开销。不过,这种方法对于简单的小函数效果较好,而对大型函数或复杂逻辑的函数,内联展开可能反而导致代码膨胀,增加程序大小,影响缓存效率。
  3. inline 不是强制的inline 只是一个请求,编译器可能会忽略它。如果编译器认为内联函数不合适(例如,函数体太复杂、包含递归调用等),它仍然可以选择不进行内联展开。
  4. 代码膨胀的风险: 内联函数虽然可以提升性能,但可能会导致代码膨胀(即生成的二进制代码变大),因为每次调用内联函数时,函数体会被直接插入到调用点。这对于嵌套或频繁调用的函数,可能导致程序大小显著增加。
  5. 定义在头文件中: 如果函数被标记为 inline,它的定义通常会被放在头文件中,因为内联函数需要在每个使用它的翻译单元(translation unit)中可见。如果内联函数定义在 .cpp 文件中,而多个翻译单元调用它,就可能导致链接错误。

例子

// 定义一个内联函数
inline int add(int a, int b) {return a + b;
}int main() {int result = add(5, 3);  // 编译器可能会将这个函数调用展开为:int result = 5 + 3;return 0;
}

在这个例子中,add 函数被声明为 inline,如果编译器决定内联展开,函数调用可能会被替换为 int result = 5 + 3;

特点和注意事项

  1. 默认内联: C++11 之后,类成员函数的定义如果写在类内,会被隐式地视为 inline 函数。例如:

    class MyClass {
    public:int add(int a, int b) { return a + b; }  // 这个函数默认是内联的
    };
    
  2. 递归函数通常不能内联: 如果一个函数是递归的,编译器通常不会进行内联展开,因为递归函数会调用自己,内联化会导致无限展开。

  3. 编译器的优化: 现代 C++ 编译器通常会自动优化内联,甚至可能会在没有标记 inline 的情况下内联展开小函数,或者忽略 inline 标记。

什么时候使用 inline

  • 适合小型、频繁调用的函数,如简单的数学运算或访问器(getter)函数。
  • 避免在复杂、长时间执行的函数上使用 inline,因为这可能导致程序体积增大,反而影响性能。
  • 在类的头文件中声明和定义成员函数时,如果函数逻辑简单,编译器会默认将其视为内联函数。

总结

  • inline 提示编译器将函数调用直接替换为函数体,减少函数调用的开销。
  • 它并不是强制性的,编译器有权决定是否进行内联展开。
  • 适用于简单且频繁调用的函数,但滥用 inline 可能会导致代码膨胀。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 基于SpringBoot+Vue+MySQL的智能物流管理系统
  • 【STL】priority_queue 基础,应用与操作
  • 2024java面试-软实力篇
  • MySQL之表内容的增删改查(含oracel 9i经典测试雇佣表下载)
  • Avalonia:自定义控件
  • Unity教程(十六)敌人攻击状态的实现
  • Spring IoC 注解 总结
  • GitLab 迁移并推送代码仓库
  • 2024永久激活版 Studio One 6 Pro for mac 音乐创作编辑软件 完美兼容
  • FortiGate硬件高级测试指南
  • 数据结构——“二叉搜索树”
  • 条件编译代码记录
  • React 项目中,如何实现有效的内存管理和防止内存泄漏?
  • 二叉树(下)
  • 【CSS in Depth 2 精译_030】5.2 Grid 网格布局中的网格结构剖析(下)
  • k8s 面向应用开发者的基础命令
  • PHP那些事儿
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • vue-router的history模式发布配置
  • WebSocket使用
  • 工程优化暨babel升级小记
  • 关于使用markdown的方法(引自CSDN教程)
  • 观察者模式实现非直接耦合
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 实现简单的正则表达式引擎
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • Prometheus VS InfluxDB
  • 哈罗单车融资几十亿元,蚂蚁金服与春华资本加持 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • ​业务双活的数据切换思路设计(下)
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #QT(QCharts绘制曲线)
  • (20)docke容器
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (leetcode学习)236. 二叉树的最近公共祖先
  • (八)c52学习之旅-中断实验
  • (笔记)Kotlin——Android封装ViewBinding之二 优化
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (三)uboot源码分析
  • (四)c52学习之旅-流水LED灯
  • (四)图像的%2线性拉伸
  • (五)IO流之ByteArrayInput/OutputStream
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .NET Core Web APi类库如何内嵌运行?
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .NET Framework 3.5安装教程
  • .Net(C#)常用转换byte转uint32、byte转float等
  • .net中的Queue和Stack
  • @JsonFormat 和 @DateTimeFormat 的区别
  • [ IOS ] iOS-控制器View的创建和生命周期
  • [AI aider] 打造终端AI搭档:Aider让编程更智能更有趣!