inline函数的使用和理解

inline函数的使用和理解在 C 中 inline 函数是一种比较小巧的函数 将函数声明为 inline 该函数就成为内联函数 内联函数使函数的调用成本大大降低 因为编译器通常会对内联函数进行优化 如果 inline 函数的本体很小 编译器对内联函数的优化会使编译后产生的目标码比不使用内联函数产生的目标码更小 编译器对内联函数一般都是对每一个调用到该内联函数的地方都以函数本体替换 所以也使其执行速率大大提高 但如果

        在C++中,inline函数是一种比较小巧的函数。将函数声明为inline,该函数就成为内联函数。内联函数使函数的调用成本大大降低,因为编译器通常会对内联函数进行优化,如果inline函数的本体很小,编译器对内联函数的优化会使编译后产生的目标码比不使用内联函数产生的目标码更小,编译器对内联函数一般都是对每一个调用到该内联函数的地方都以函数本体替换,所以也使其执行速率大大提高。但如果使用不得当,大量的本体替换也可能会使最终的目标码很大,这对一台内存有限的嵌入式机器来说,反而会有相反的结果,所以合理的理解并使用inline函数是很有必要的。

        1、inline函数经常可以用来替换一些形似函数的宏,如:

//以a和b较大的值调用func函数 #define CALLMAX(a, b) func((a) > (b) ? (a) : (b))

        按这个宏的操作方式,如果这样使用:

int a = 5, b = 0; CALLMAX(++a, b); //func(7) -> a = 7, b = 0; CALLMAX(++a, b + 10); //func(10) -> a = 6, b =10

        使用宏的方式,会使a被异常累加,会影响后面对变量a的使用。所以以宏去实现一个形似函数的功能不如使用inline函数替换:

template<typename T> inline void callMax(const T& a, const T& b) { func(a > b ? a : b); }

        除了将这样的宏使用inline替换可以防止参数被更改,且inline函数也是函数,它有作用域一说,可以将其定义为class的private成分,一般来说,宏没有这种功能。

        2、inline的隐式和显式声明:

        inline函数有隐式和显式两种声明方式,隐式的声明方式如这样:

class Animal { public: ... int number() const { return theNum; } //隐式的inline ... private: int theNum; };

        显式声明就是直接在函数定义式前加inline声明,如上面第1条中的程序。

        3、inline函数通常都置于头文件内:

        因为inline函数通常都是编译器将函数本体替换到所调用的地方,所以一般都将inline函数声明到头文件内。但它与template无关,在很多代码中,经常见到使用template声明的接口总是使用inline声明,其实它们是无关联的,在需要inline的时候就是用inline,不需要inline的时候就不要使用inline。

        4、无法被inline的情况:

        如果函数比较复杂,比如内部有循环或递归的函数,或有对virtual函数的调用声明为inline,则编译器无法真正将它inline化。或者,当使用函数指针的方式去调用内联函数时,也是无法真正inline化的:

inline void func() {...} //func为一个声明为inline的函数 void (*pfunc)() = f; //pfunc指向f ... func(); //这种调用可以被inline pfunc(); //这种调用不能够被inline

        5、尽量不要对构造函数和析构函数inline:

        假如有这样的两个继承类:

class Base { public: ... private: std::string bm1, bm2; }; class Derived: public Base { public: Derived() {} //inline,但实现是空的 ... private: std::string dm1, dm2; };

        对继承类Derived的构造函数隐式inline,虽然看起来里面是一个空实现,但实际上,在编译器看来,内部其实被本体替换为(大致代码):

Derived::Derived() { Base::Base(); //继承类构造函数首先先调用其基类的构造函数 try { dm1.std::string::string(); } catch(...) { Base::~Base(); throw; } try { dm2.std::string::string(); } catch(...) { dm1.std::string::~string(); Base::~Base(); throw; } }

        这只是很小的类,如果类很大,内部的声明变量众多,且继承关系复杂,将构造函数inline化,会使代码更加膨胀,有可能会影响性能和速度。所以最好不要对构造和析构函数inline。

        6、不要过多的使用inine函数:

        inline函数的特点使得在过多使用inline函数时,会使代码的可移植性降低。如果func函数是inline函数,那么一旦哪一天改变了func函数的实现方式,那所有用到func函数的地方都需要重新编译。并且,对程序调试而言,大部分inline函数无法调试,所以如果使用过多,代码的可调试性也会降低。所以,一般都是在在小型且调用很频繁的函数身上,将其声明成inline函数,是程序的效率提升上去。这就是inline函数的一般使用原则。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/231825.html原文链接:https://javaforall.net

(0)
上一篇 2025年11月19日 上午8:01
下一篇 2025年11月19日 上午8:22


相关推荐

  • 网站前端和后台性能优化21

    网站前端和后台性能优化21

    2022年3月13日
    44
  • 万亿模型Kimi K2开源登顶:开源第一只是序章

    万亿模型Kimi K2开源登顶:开源第一只是序章

    2026年3月12日
    3
  • 腾讯元宝 2.37.0.617 正式版

    腾讯元宝 2.37.0.617 正式版

    2026年3月13日
    3
  • js打印html5,控制台打印文字效果js插件-typed.js

    js打印html5,控制台打印文字效果js插件-typed.jstyped js 是一款模拟控制台打印文字效果的 js 插件 typed js 可以自由的控制要打印的文字 以及打印的速度等 可以制作出逼真的打印文字效果 安装可以通过 bower 来安装 typed js 插件 bowerinstall js 使用方法在页面中引入 jquery 和 typed js 文件 HTML 结构使用一个元素来作为打印控制台容器 初始化插件可以通过纯 js 的方法来初始化 type js 插件

    2026年3月26日
    2
  • 拆解量化交易模型

    拆解量化交易模型量化交易看起来似乎就是用机器炒股,没什么大惊小怪的。但是我们拆解开量化交易的模型,您就知道其中的奥秘了。首先是输入环节:假如你是量化交易建模师。你把各种你觉得会影响股价波动的重要因素的相关数据输入到程序中。我们把常用的一种多因子选股的模型展示给大家。各种因子,您就可以理解为是炒股要看的内容。比如普通人要看公司、行业、估值、成交量、业绩等。这些都可以作为因素,将其内含数据包输入到程序里,当做因子之一。估值类因子1、预测最近年度每股股利2、未来12个月预测净利润3、每股收益

    2022年6月26日
    31
  • html播放rtsp流,浏览器播放rtsp视频流解决方案

    html播放rtsp流,浏览器播放rtsp视频流解决方案最近项目中需要实时播放摄像头rtsp视频流,于是就专门做了些研究。而浏览器不能直接播放,只有通过插件或者转码来实现这个需求。要实现这个目的,可以采用的方案非常得多,有商业的也有开源的,这里主要列举一些开源的方案。这里的方案都是我尝试过了的,有些成功,有些没成功。但是因为每个项目情况不同,这次没成的方法,换个项目也许就能成。方案一:html5+websocket_rtsp_proxy实现视频…

    2022年10月17日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号