[C++] C++基础之inline的使用

文章目录

  • 1. 为什么要使用inline
  • 2. inline如何减少调用开销的,与宏有什么区别
    • 2.1 inline如何工作的?
    • 2.2 与宏的区别?
  • 3. 那么inline会强制有效吗?
  • 4. 在函数声明前使用inline有效吗?
  • 5. 绝对不会inline的函数有哪些?
  • 6. 有哪些函数会自动隐式内联
  • 7. 为什么要求我们只对小的函数进行inline?
  • 8. 为什么inline函数多定义在header文件中
  • 9. 内联函数可以用函数指针方式使用吗?
  • 10. 虚函数不可inline?
  • 11. inline函数在程序设计方面有什么影响吗?
  • 12. 一个函数可以强制不内联或者强制内联
  • 13. Google Code Guide经验法则
  • Reference

总的使用原则: 慎重使用inline,一般可以考虑不用inline,只在能有效减少调用耗时的情况下使用inline;实际编程时最初的原则是不要内联任何函数,除非函数确实很小很简单。

1. 为什么要使用inline

当一个小的函数被非常频繁的调用时,我们为了减少不必要的计算开销,会将其声明为inline,这样就在没有调用开销的情况下使用这个函数。

知识点1: 使用inline的目的是减少函数调用开销,所以只有调用开销相对于函数执行很大时inline的意义才更大。

2. inline如何减少调用开销的,与宏有什么区别

2.1 inline如何工作的?

  • inline基本思想在于将每个函数调用以它的代码体来替换

2.2 与宏的区别?

既然都是平替代码,那么inline和宏又有什么区别(感觉都是一种替换策略),这就需要说到宏存在的两个问题

  • 宏定义在形式上类似于一个函数,但在使用它时,仅仅只是做预处理器符号表中的简单替换,因此它不能进行参数有效性的检测,也就不能享受C++编译器严格类型检查的好处;另外它的返回值也不能被强制转换为可转换的合适的类型
  • 在C++中引入了类及类的访问控制,这样,如果一个操作或者说一个表达式涉及到类的保护成员或私有成员,你就不可能使用这种宏定义来实现

知识点2: inline 推出的目的,也正是为了取代这种表达式形式的宏定义,它消除了宏定义的缺点,同时又很好地继承了宏定义的优点。

3. 那么inline会强制有效吗?

不会, inline 就像register一样,只是对编译器提示作用,编译器会根据实际代码情况决定是否对函数进行inline操作。比如,你将一个递归函数指定为inline,编译器就会忽略这个inline,将这个函数还原成普通函数。

知识点3: inline只是提示作用而不是强制的

4. 在函数声明前使用inline有效吗?

inline只在函数定义时使用是有效的,在函数的声明时使用没有意义。

知识点4: inline只有在函数定义时使用才有效。

5. 绝对不会inline的函数有哪些?

  • 包含循环和递归函数,某些虚函数

知识点5: inline的死对头。

6. 有哪些函数会自动隐式内联

  • 对于类方法,定义在类体内部的一些方法自动成为内联方法。 比如getter 和setter函数; 但是注意不要在构造和析构函数中使用,虽然这两类函数显式的代码体小,但是隐式的代码体会很大(因为存在大量对成员变量的初始化和销毁操作在),所以实际上inline可能是作用在大函数体上的,从而带来inline的副作用(代码膨胀和失效。)

知识点6: 类中一些方法会自动成为内联方法。内联函数最重要的使用地方是用于类的存取函数。

7. 为什么要求我们只对小的函数进行inline?

因为长而复杂的函数使用inline存在两个问题:

  • 复杂的函数用inline没有优势:inline函数通过省去函数调用的开销,从而提高函数的执行效率,但是如果函数体内代码的执行时间相比于函数调用时间长的多的话,inline函数也就没有什么优势了。
  • 长且复杂的函数inline会让代码膨胀(因为平替),增加整个目标代码的体积,而过分地使用内联所产生的程序会因为有太大的体积而导致可用空间不够。即使可以使用虚拟内存,内联造成的代码膨胀也可能会导致不合理的页面调度行为(系统颠簸),这将使你的程序运行变慢;此外过多的内联还会降低指令高速缓存的命中率,从而使取指令的速度降低。

如果函数小,会缩减目标代码的大小(少了调用代码)

知识点7: inline只在小函数上使用会有好处。

8. 为什么inline函数多定义在header文件中

  • 在调用内联函数时,要保证内联函数的定义让编译器"看"到,也就是说内联函数的定义要在头文件中,这与通常的函数定义不一样。

特殊情况,inline函数在header中会有问题,比如inline函数因为一些原因,不能被编译器内联,那么?

  • 旧的编译器规则:对于未被内联的内联函数,编译器把它当成被声明为static 那样处理,即,使它局限于当前被编译的文件。 但是如果这个内联函数中有static局部变量,那么就会存在静态局部变量会存在两份拷贝的情况。
  • 新的编译器规则:为f生成代码时就象它是一个普通的"外联"函数一样, 可以理解为extern 指示的函数一样。

知识点8: inline函数一般建议在header中定义,但是需要考虑inline失效的情况下导致的问题。 比如:如果函数中包含静态对象,通常要避免将它声明为内联函数。

9. 内联函数可以用函数指针方式使用吗?

  • 如果程序中要取一个内联函数的地址,编译器就必须为此生成一个函数体。 也就是没有了函数体平替的机制。

知识点9: inline函数使用函数指针传递,则不会执行inline的平替机制。

10. 虚函数不可inline?

  • 一般来说虚函数不要inline
  • The main reason for making a virtual function inline is to place its definition in the class, either for convenience or to document its behavior, e.g., for virtual accessors and mutators.

11. inline函数在程序设计方面有什么影响吗?

  • 如果过多的使用inline函数,那么想对程序库中的内联函数进行二进制代码升级是不可能的。换句话说,如果Func是库中的一个内联函数,使用方会将Func的函数体编译到自己的程序中。如果程序库的设计者后来要修改Func,所有使用Func的用户程序必须重新编译。相反,如果Func是非内联函数,对f的修改仅需要用户重新链接,这就比需要重新编译大大减轻了负担;如果包含这个函数的程序库是被动态链接的,程序库的修改对用户来说完全是透明的。

12. 一个函数可以强制不内联或者强制内联

目的是什么?

__noinline__ void function();
__forceinline__ void function();

13. Google Code Guide经验法则

  • 最好inline不超过10行的函数:A decent rule of thumb is to not inline a function if it is more than 10 lines long. Beware of destructors, which are often longer than they appear because of implicit member- and base-destructor calls!
  • inline函数中最好不要有循环或switch: Another useful rule of thumb: it’s typically not cost effective to inline functions with loops or switch statements (unless, in the common case, the loop or switch statement is never executed).

Reference

  • https://google.github.io/styleguide/cppguide.html#Inline_Functions
  • https://www.cnblogs.com/yaowen/p/4777810.html
  • Effective C++: 条款30 彻底了解inlining的里里外外
  • https://upimg.baike.so.com/doc/6842554-7059853.html
  • https://www.cnblogs.com/alex-tech/archive/2011/03/24/1994273.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/556805.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JetBrains Rider 2024.1.1 .NET集成开发环境 mac/win

JetBrains Rider是一个新的跨平台的基于Inte lliJ平台和ReSharper的. NET集成技术开发工作环境。 Rider提供了大量人工智能系统代码进行编辑管理功能,如不同类型的代码可以完成、自动设备名称发展空间设计导入、自动通过插入大括号和突出研究显示信息匹配作为分隔符…

torchEEG工具箱

文章信息: 题目:TorchEEGEMO:基于脑电图的情绪识别深度学习工具箱 期刊:Expert Systems with Applications 环境:pytorch 1.11.0 CUDA 11.3 摘要: ​ 一个python工具箱TorchEEG,将工作流程分为五个模块…

软考 - 系统架构设计师 - 架构风格例题

问题一: 什么是软件架构风格? 软件架构风格指特定软件系统组织方式的惯用模式。组织方式描述了系统的组成构件和这些构件的组织方式。惯用模式反映了众多系统所共有的结构和语义。 集成开发环境与用户的交互方式 (实际上询问在交互方面&am…

干货-PMP常考知识点,都给你们汇总到这里了

PMP认证考试考来考去,其实就是那些知识点。把这些知识点吃透了,你会发现做题稳准狠。不仅速度快,正确率也有很大的提升。 我们结合了10几年PMP备考辅导经验,给大家梳理了这些PMP常考的知识点集锦,希望能帮到大家&#…

css中all 的使用记录

all 在 CSS 中是一个特殊的属性值,它允许我们重置元素或元素父级的所有属性到其初始值、继承的值或取消设置的值。这一属性非常有用,特别是在需要快速重置多个属性的情况下,它避免了逐一设置每个属性的繁琐过程。 先看一下浏览器兼容性&#…

【SAP HANA 15】SQL锁表 (查询,解锁)

锁表查看 --锁表检查语句 SELECT C.CONNECTION_ID,PS.STATEMENT_STRINGFROM M_CONNECTIONS C JOIN M_PREPARED_STATEMENTS PSON C.CONNECTION_ID PS.CONNECTION_ID AND C.CURRENT_STATEMENT_ID PS.STATEMENT_IDWHERE C.CONNECTION_STATUS RUNNINGAND C.CONNECTION_TYPE Re…

第二届数据安全大赛暨首届“数信杯”数据安全大赛数据安全积分争夺赛-东区预赛部分WP

这里写目录标题 检材下载:1.理论题2.数据安全:pb:Sepack: 3.数据分析:数据分析(1)数据分析1-1:数据分析1-2:数据分析1-3: 数据分析(3)数据分析3-1:数据分析3-2&#xff1…

2024年04月18日优雅草便民tools开源-git以及dcloud同步-长期更新

优雅草小工具-数据来自优雅草api赋能 优雅草小工具-数据来自优雅草api赋能-优雅草便民工具是一款由成都市一颗优雅草科技有限公司打造的便民查询公益工具,2024年1月17日正式发布v1.0.0版本,本工具为了方便大众免费使用,本生活小工具会陆续加入…

Oracle——领先的企业级数据库解决方案

一、WHAT IS ORACLWE: ORACLE 数据库系统是美国 ORACLE 公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S 体系结构的数据库之一,ORACLE 通常应用于大型系统的数…

C#基于SSE传递消息给Vue前端实现即时单向通讯

一、简述 通常前端调用后端的API,调用到了,等待执行完,拿到返回的数据,进行渲染,流程就完事了。如果想要即时怎么办?如果你想问什么场景非要即时通讯,那可就很多了,比如在线聊天、实…

gpt能生成ppt吗

gpt能生成ppt吗 GPT是一个高度通用的工具,适用于多种场景和领域,制作ppt只是它强大功能的冰山一角,具体包括: 信息查询与解释: 提供科学、技术、历史、文化等领域的详细解释和背景信息。 解答疑问,帮助…

前端css中transition的使用

前端css中transition的使用 一、前言二、transition的4个属性三、例子1.源码12.源码1运行效果 四、结语五、定位日期 一、前言 CSS中的transition(过渡),根据字面意思就可以理解成一种变化状态的过程。当我们有一个方形,我们想让…

Java在MySQL数据报错Data truncation: Data too long for column ‘**‘ at row 1 处理

问题 在Java SpringBoot MyBatis 框架的项目中,一切正常,不过在一个接口的参数字段传入过大的数据就会报此错误: 请求常:org.springframework.dao.DataIntegrityViolationException: Error updating database.Cause:com.mysql.cj.jdbc.excep…

漫画项目管理 | 遇到强势甲方的不合理项目需求,我该怎么办?

🤷‍♂️ 遇到甲方强烈要求不合理需求怎么办? 🤸‍♂️看似离谱的功能客户却一定要加? 🤹‍♂️时间紧任务重,甲方却“什么都想要“? 🤾‍♂️明明初稿很完美,却被要求改来改去?** 👨‍…

学习STM32第十六天

RTC实时时钟 一、简介 RTC是一个独立的BCD格式定时器,提供一个时钟日历,两个可编程报警中断,一个具有中断功能周期性可编程唤醒标志,RTC和时钟配置系统处于后备区域。 通过两个32位寄存器以BCD格式实现秒、分钟、小时&#xff08…

Qt日志使用

QsLog使用 这篇讲qt的日志还是比较好的,可以在自己的函数里面配置这个日志框架实现自己所需的功能。 我接触的项目里面,假如有个函数功能执行错误了,我希望可以快速定位到这个错误,这个时候就需要到了日志,我咨询了有经…

使用Python脚本检测服务器信息并定时发送至管理员邮箱

在日常的系统管理工作中,监测服务器的资源占用情况至关重要,我们需要及时获得通知以便采取相应措施。我新装了一台UbuntuServer服务器,写了一个可以定期收集服务器的CPU、内存、网络和磁盘信息,并通过邮件将这些信息发送给管理员的…

Seal^_^【送书活动第一期】——《Vue.js+Node.js全栈开发实战(第2版)》

Seal^_^【送书活动第一期】——《Vue.jsNode.js全栈开发实战(第2版)》 一、参与方式二、本期推荐图书2.1 前 言2.2 作者简介2.3 图书简介2.4 本书特色2.5 编辑推荐2.6 书籍目录 三、正版购买 一、参与方式 1、关注博主的账号。 2、点赞、收藏、评论博主的…

C++练级之路——类和对象(下)

目录 1、构造函数初始化列表 2、类型转换 3、explicit关键字 4、static成员 5、友元 友元函数 友元类 6、内部类 7、匿名对象 8、拷贝构造时的一些编译器优化 差不多结束了,类和对象! 1、构造函数初始化列表 初始化列表:以一个冒号…

了解MySQL的复制

了解MySQL的复制 MySQL的复制允许数据从一个MySQL数据库服务器(主服务器)复制到一个或多个MySQL数据库服务器(从服务器)。复制在数据库的扩展性和数据备份方面扮演着重要角色,特别是在大型企业和高可用性的应用场景中…
最新文章