C++内联函数解析

咱们一起学C++ 第一百三十九篇:之内联函数与宏的练习题解析 在C++的学习之路上,我们一同前行,每一次练习都是成长的机会。此次,我们将对与内联函数和宏相关的练习题进行详细解析,帮助大家巩固所学知识,深入理解内联函数和宏的特性、使用方法以及它们之间的区别。通过实际解题,大家能够更好地掌握这些重要的编程概念,提升C++编程能力,共同在C++的知识海洋中继续进步。 阅读详情

C++内联函数解析  

2010-10-14 00:24:53|  分类: C++ |字号 订阅

源自:

http://www.cnblogs.com/berry/articles/1582702.html

http://baike.baidu.com/view/1365655.htm?fr=ala0_1

 

优点:

  1. inline 定义的类的内联函数,函数的代码被放入符号表中,在使用时直接进行替换,(像宏一样展开),没有了调用的开销,效率也很高。

  2.很明显,类的内联函数也是一个真正的函数,编译器在调用一个内联函数时,会首先检查它的参数的类型,保证调用正确。然后进行一系列的相关检查,就像对待任何一个真正的函数一样。这样就消除了它的隐患和局限性。

  3. inline 可以作为某个类的成员函数,当然就可以在其中使用所在类的保护成员及私有成员。

 

(一)inline函数(摘自C++ Primer的第三版)

在函数声明或定义中函数返回类型前加上关键字inline即把min()指定为内联。

      inline int min(int first, int secend) {};

inline 函数对编译器而言必须是可见的,以便它能够在调用点内展开该函数。与非inline函数不同的是,inline函数必须在调用该函数的每个文本文件中定义。当然,对于同一程序的不同文件,如果inline函数出现的话,其定义必须相同。对于由两个文件compute.C和draw.C构成的程序来说,程序员不能定义这样的min()函数,它在compute.C中指一件事情,而在draw.C中指另外一件事情。如果两个定义不相同,程序将会有未定义的行为:

      为保证不会发生这样的事情,建议把inline函数的定义放到头文件中。在每个调用该inline函数的文件中包含该头文件。这种方法保证对每个inline函数只有一个定义,且程序员无需复制代码,并且不可能在程序的生命期中引起无意的不匹配的事情。

 

(二)内联函数的编程风格(摘自高质量C++/C 编程指南)

关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。

如下风格的函数Foo 不能成为内联函数:

inline void Foo(int x, int y); // inline 仅与函数声明放在一起

void Foo(int x, int y){}

而如下风格的函数Foo 则成为内联函数:

void Foo(int x, int y);

inline void Foo(int x, int y) // inline 与函数定义体放在一起{}

所以说,inline 是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了inline 关键字,但我认为inline 不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。

 

定义在类声明之中的成员函数将自动地成为内联函数

例如

class A

{

    public:void Foo(int x, int y) {  } // 自动地成为内联函数

}

将成员函数的定义体放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该改成:

// 头文件

class A

{

    public:

    void Foo(int x, int y);

}

// 定义文件

inline void A::Foo(int x, int y){} 

 

慎用内联

内联能提高函数的执行效率,为什么不把所有的函数都定义成内联函数?如果所有的函数都是内联函数,还用得着“内联”这个关键字吗?内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。

 

以下情况不宜使用内联:

(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。

(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline 不应该出现在函数的声明中)。


注意点:


内联函数既能够去除函数调用所带来的效率负担又能够保留一般函数的优点。然而,内联函数并不是万能药,在一些情况下,它甚至能够降低程序的性能。因此在使用的时候应该慎重。

   
     1.我们先来看看内联函数给我们带来的好处:从一个用户的角度来看,内联函数看起来和普通函数一样,它可以有参数和返回值,也可以有自己的作用域,然而它却不会引入一般函数调用所带来的负担。另外,它可以比宏更安全更容易调试。  
    当然有一点应该意识到,inline   specifier仅仅是对编译器的建议,编译器有权利忽略这个建议。那么编译器是如何决定函数内联与否呢?一般情况下关键性因素包括函数体的大小,是否有局部对象被声明,函数的复杂性等等。

   
     2.那么如果一个函数被声明为inline但是却没有被内联将会发生什么呢?理论上,当编译器拒绝内联一个   函数的时候,那个函数会像普通函数一样被对待,但是还会出现一些其他的问题。

例如下面这段代码:  
  //   filename   Time.h  
  #include<ctime>  
  #include<iostream>  
  using   namespace   std;  
  class   Time  
  {  
  public:  
          inline   void   Show()  

          {  
              for (int   i   =   0;   i<10;   i++)
                  cout<<time(0)<<endl;
          }  
  };   
因为成员函数Time::Show()包括一个局部变量和一个for循环,所以编译器一般拒绝inline,并且把它当作一个普通的成员函数。但是这个包含类声明的头文件会被单独的#include进各个独立的编译单元中:  
  //   filename   f1.cpp  
  #include   "Time.h"  
  void   f1()  
  {  
          Time   t1;  
          t1.Show();  
  }  
  //   filename   f2.cpp  
  #include   "Time.h"  
  void   f2()  
  {  
          Time   t2;  
          t2.Show();  
  }  
  结果编译器为这个程序生成了两个相同成员函数的拷贝:  
  void   f1();  
  void   f2();  
  int   main()  
  {  
          f1();    
          f2();  
          return   0;  
  }  
     当程序被链接的时候,linker将会面对两个相同的Time::Show()拷贝,于是函数重定义的连接错误发生。但是老一些的C++实现对付这种情况的办法是通过把一个un-inlined函数当作static来处理。因此每一份函数拷贝仅仅在自己的编译单元中可见,这样链接错误就解决了,但是在程序中却会留下多份函数拷贝。在这种情况下,程序的性能不但没有提升,反而增加了编译和链接时间以及最终可执行体的大小。但是幸运的是,新的C++标准中关于un-inlined函数的说法已经改变。一个符合标准C++实现应该只生成一份函数拷贝。然而,要想所有的编译器都支持这一点可能还需要很长时间。

 
     另外关于内联函数还有两个更令人头疼的问题。第一个问题是该如何进行维护。一个函数开始的时候可能以内联的形式出现,但是随着系统的扩展,函数体可能要求添加额外的功能,结果内联函数就变得不太可能,因此需要把inline   specifier去除以及把函数体放到一个单独的源文件中。另一个问题是当内联函数被应用在代码库的时候产生。当内联函数改变的时候,用户必须重新编译他们的代码以反映这种改变。然而对于一个非内联函数,用户仅仅需要重新链接就可以了。 

 
     这里想要说的是,内联函数并不是一个增强性能的灵丹妙药。只有当函数非常短小的时候它才能得到我们想要的效果,但是如果函数并不是很短而且在很多地方都被调用的话,那么将会使得可执行体的体积增大。最令人烦恼的还是当编译器拒绝内联的时候。在老的实现中,结果很不尽人意,虽然在新的实现中有很大的改善,但是仍然还是不那么完善的。一些编译器能够足够的聪明来指出哪些函数可以内联哪些不能,但是,大多数编译器就不那么聪明了,因此这就需要我们的经验来判断。如果内联函数不能增强行能,就避免使用它!



C++内联函数:为什么必须定义在头文件中?ODR规则与实战解析 在C++编程中,单一定义规则(ODR)是确保程序正确链接和运行的基础性原则,它要求任何函数或变量在程序中只能有一个定义。为了在多个翻译单元中共享函数实现同时避免链接错误,C++引入了inline关键字的特殊语义——它允许同一函数在多个编译单元中存在相同定义,链接器会自动选择并合并。这一机制不仅提升了小型、高频调用函数的执行效率,也为头文件中的工具函数、类内成员函数以及constexpr函数提供了安全定义的基础。从工程实践角度看,理解inline与ODR的配合,能有效解决跨文件代码复用时的“多重定义”错误,确 阅读详情

相关推荐

C++内联函数使用案例解析

内联函数是C++中一种特殊的函数,它通过关键字inline告诉编译器,希望将函数调用的指令替换为函数体本身,以减少函数调用的开销。内联函数的基本特点包括:- 函数体被嵌入到每个调用点,避免了常规函数调用时的参数压栈和返回地址的存储等操作。- 内联函数的使用应谨慎,因为过多的内联可能会导致生成的代码体积过大。- 内联函数有助于减少函数调用的开销,但不会减少参数传递的开销。

weixin_35755640的博客 881

C++内联函数

C++内联函数

mids520的博客 224

HALCON深度学习模型部署新选择:一份详细的OpenVINO 2021.4 LTS集成与配置避坑指南

本文详细介绍了如何将HALCON深度学习模型与OpenVINO 2021.4 LTS集成,提供环境配置、硬件加速优化及故障排除的实用指南。特别针对Intel独立显卡的AI加速器接口进行优化,帮助机器视觉工程师提升AI推理效率,适用于工业检测等高要求场景。

weixin_42531779的博客 238

C/C++ 之内联函数

  在C中可以使用#define提高执行效率,但是容易出错,而在C++ 支持函数内联,其目的亦是如此。 (1)inline的工作原理:   对于任何内联函数,编译器在符号表里放入函数声明(包括名字,参数类型,返回值类型)。如果编译器没有发现内联函数存在错误,那么该函数的代码也被放入符号表中。在调用一个内联函数时,编译器首先检查调用是否正确,比如进行类型安全检查,进行类型转换等。如果正...

all36426的博客 156

5G NR 帧结构

本节主要介绍5G NR中的帧结构[38.211-4.3]。5G帧结构(Frame Structure)为时域结构。其设计比其4G LTE更为灵活,这种灵活性使5G能够根据应用需求(如增强移动宽带eMBB,超高可靠低时延通信URLLC)进行调整,同时支持差异化的应用场景,提高了5G的利用效率与响应能力。具体而言,5G帧结构是基于时隙和OFDM符号设计的,且5G网络能够根据服务需求动态调整各时隙持续时长。

夫子喵的博客 5286

Cesium高效渲染海量GeoJSON数据的7种优化策略与实战解析

本文深入解析Cesium高效渲染海量GeoJSON数据的7种优化策略,包括瓦片化转换、LOD分级加载、数据简化等关键技术。通过实战案例展示如何解决渲染卡顿问题,提升矢量数据加载性能,实现流畅的60FPS交互体验。特别针对GeoJSON大数据量场景提供完整优化方案。

h0i1j2k3l的博客 933

C++复习之内联函数

内联函数与普通函数的区别 内联函数在编译过程中,没有函数调用的开销,在函数的调用点直接把函数的代码进行展开处理。inline函数如果内联成功,在符号表内不再产生相应的函数符号。 普通函数在函数调用点有调用过程,进行参数压栈,函数栈帧的开辟和回退过程,有函数调用的开销。 如果一个函数在短时间内被大量调用,且函数本身比较简答,建议将此函数设置为内联函数。 注意: inline只是建议编译器把这个函数处...

mlc741295821的博客 238

PCB设计AD规则设置(按照嘉立创设置)

按照嘉立创的相关加工能力进行设置: 1.Hole Size(钻孔孔径) 嘉立创要求钻孔孔径在0.2-6.3mm,并给了公差(如下图给出了钻孔孔径和公差) 规则设置位置:Manufacturing->Hole Size,这里就改一下数值,最小设置为0.2mm,最大设置为6.3mm 2.Width(线宽) 嘉立创要求线宽多层板双层板最小为3.5mil,单双层板最小为5mil(如下图给出了线宽) 规则设置位置:Routing->Width,我目前只画过双层板,按我的设置如下,最小的线宽设置为10

subtitle_的博客 4万+

『 C++ 』内联函数

内联函数的原理和使用.

weixin_72040293的博客 742

Windows 11下Dify安装部署实战指南

本文详细介绍在Windows 11环境下部署开源LLM应用开发平台Dify的完整流程。涵盖环境准备(WSL 2启用、Docker Desktop安装配置)、源码获取、Docker容器化部署、数据库初始化、服务启动验证等核心步骤。包括环境变量配置、性能优化、安全加固、端口冲突解决、数据库连接故障排查等关键技术要点。为开发者提供从零到一的Dify本地化部署实战指南

weixin_44269410的博客 851

别再死记硬背了!用Python可视化带你直观理解柯西收敛定理(附NumPy代码)

本文通过Python可视化技术,结合NumPy和Matplotlib,直观展示柯西收敛定理的动态过程。文章提供了完整的代码实现,帮助读者从抽象数学定义过渡到具象理解,特别适合数学学习者和Python开发者。通过热力图和交互式参数探索,读者可以清晰观察数列收敛特性,提升数学分析的学习效率。

weixin_28465009的博客 185

C++中内联函数的定义和使用

引入内联函数的目的是为了解决程序中函数调用的效率问题。 函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方 法,而不必关心函数功能的具体实现;函数的引入可以减少程序的目标代码,实 现程序代码和数据的共享。但是,函数调用也会带来降低效率的问题,因为调用 函数实际上将程序执行顺序转移到函数所存放在内存中某个地址,将函数的程序 内容执行完后,再返回到转去执行该函数前的地方。这种转移操作

hbyzl的专栏 1305

RT-Thread 5.1.0 实战:手把手教你用CubeMX和RT-Studio创建第一个工程(附常见编译错误修复)

本文详细介绍了如何使用STM32CubeMX和RT-Thread Studio 5.1.0创建第一个RT-Thread工程,包括开发环境准备、CubeMX配置、工程整合及常见编译错误修复。通过实战指南,帮助开发者快速上手RT-Thread 5.1.0,解决开发过程中的典型问题,提升嵌入式开发效率。

weixin_29165465的博客 285

C++ 中内联函数 inline “无法解析的外部符号” 问题

  复习C++时碰到了使用内联函数inline的情况。   其实情况也很简单,我在.h的类定义中声明了成员函数,在.cpp的实现中加入了inline关键词。编译器不断报错,“无法解析的外部符号”。情况即为下方:   在.h文件中: class A { public: void show(); };   在.cpp中: inline void A::show()...

weixin_30786657的博客 921

GEPA_AIME教程:使用GEPA优化数学问题求解的完整指南

本教程展示了如何使用DSPy框架中的GEPA(Generative Evolutionary Prompt Adaptation)优化器来提升大语言模型在数学竞赛问题(AIME)上的表现。# 创建基础的链式思考程序"""带有详细反馈的评估指标,为GEPA提供学习信号"""try:# 处理解析错误feedback_text = f"最终答案必须是一个有效的整数。你回答了'

步子哥的博客 1384

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

【C++】内联函数深度解析(什么是内联函数?为什么要使用内联函数?)

本文介绍了C++内联函数的概念,其如何在编译时展开以提高效率,以及与宏函数的区别。内联函数适用于短小频繁调用的情况,但并非所有函数都适合。还讨论了内联函数的优缺点和是否一定能被编译器展开的问题。

weixin_45031801的博客 4776

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

深入解析C++内联函数:概念、原理与实践

内联函数的定义看似简单,仅需在普通函数定义前加上inline关键字。但别小看这简简单单的inline,它背后蕴含着编译器优化的大学问。内联函数的提出,旨在解决宏函数的种种弊端,同时继承宏无需函数调用开销的优势。#endif将内联函数定义直接置于头文件中,避免声明与定义分离导致的链接错误。优势:继承宏函数无调用开销的优点,同时支持调试、具备类型检查,代码可读性强。局限:仅适用于小型、频繁调用的函数;编译器对内联请求拥有最终决定权。最佳实践优先以内联函数替代宏函数实现性能敏感逻辑。

w_437646的博客 863

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C++内联函数机制全面解析

内联函数机制的引入 内联机制被引入C++作为对宏(Macro)机制的改进和补充(不是取代)。内联函数的参数传递机制与普通函数相同。但是编译器会在每处调用内联函数的地方将内联函数的内容展开。这样既避免了函数调用的开销又没有宏定义机制的缺陷。由此可见,内联函数机制的引入与宏定义有很大关系,因此,有必要先了解下宏定义有哪些缺陷。 1. 由于宏定义都是直接嵌入代码中的,所以代码可能相对多一点;

Hopefully Sky的博客 4104

c++内联函数解析(inline)

一、基本定义 inline是C++语言中的一个关键字,可以用于程序中定义内联函数,inline的引进使内联函数的定义更加简单。说到内联函数,这里给出比较常见的定义,内联函数是C++中的一种特殊函数,它可以像普通函数一样被调用,但是在调用时并不通过函数调用的机制而是通过将函数体直接插入调用处来实现的,这样可以大大减少由函数调用带来的开销,从而提高程序的运行效率。一般来说inline用...

好习惯成就伟大 722

C++引用与内联函数深度解析

引用并不会开辟新空间。

SEVEN_WIND的博客 784

C++中的内联函数:深入解析与应用

内联函数是C++中的一种特殊函数,它在编译时被展开,即将函数调用替换为函数体本身。这意味着在程序运行时,不会发生函数调用的开销,如栈的维护、参数的传递和返回值的处理等。内联函数通常用于短小且频繁调用的函数,以提高程序的执行效率。在C++中,可以通过在函数定义前加上inline关键字来声明一个内联函数。这里,add函数被声明为内联函数。然而,值得注意的是,inline关键字仅仅是一个向编译器发出的请求,编译器可以选择忽略这个请求。编译器会根据函数的复杂性和大小,以及优化策略来决定是否将函数内联化。

shiming8879的博客 1321
上一篇: avaist for linux
下一篇: C++ int转string string转int 完美实现
MrBugYang
博客等级 码龄18年 21粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值