C++ inline 函数简介

C++ inline 函数简介inline 函数由 inline 关键字定义 引入 inline 函数的主要原因是用它替代 C 中复杂易错不易维护的宏函数

1.简介

inline 函数由 inline 关键字定义,引入 inline 函数的主要原因是用它替代 C 中复杂易错不易维护的宏函数。

2.编译器的处理办法

比如如下代码:

// 求 0-9 的平方 inline int inlineFunc(int num) { 
    if(num>9||num<0) return -1; return num*num; } int main(int argc,char* argv[]) { 
    int a=8; int res=inlineFunc(a); cout<<"res:"<<res<<endl; } 

inline 之后的 main 函数代码类似于如下形式:

int main(int argc,char* argv[]) { 
    int a = 8; { 
    int _temp_b=8; int _temp; if (_temp_q >9||_temp_q<0) _temp = -1; else _temp =_temp*_temp; b = _temp; } } 

经过以上处理,可消除所有与调用相关的痕迹以及性能的损失。inline 通过消除调用开销来提升性能。

3.使用方法

函数定义时,在返回类型前加上关键字 inline 即把函数指定为内联,函数申明时可加也可不加。但是建议函数申明的时候,也加上 inline,这样能够达到”代码即注释”的作用。

使用格式如下:

inline int functionName(int first, int secend,...) { 
   //}; 

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 与函数定义体放在一起。 

4.优缺点

从上面可以知道,inline 函数相对宏函数有如下优点:

(1)内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。

(2)内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。

例如宏函数和内联函数:

// 宏函数 #define MAX(a,b) ((a)>(b)?(a):(b)) // 内联函数 inline int MAX(int a,int b) { 
    return a>b?a:b; } 

使用宏函数时,其书写语法也较为苛刻,如果对宏函数出现如下错误的调用,MAX(a,"Hello"); 宏函数会错误地比较int和字符串,没有参数类型检查,但是使用内联函数的时候,会出现类型不匹配的编译错误。

(3)在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。

(4)内联函数在运行时可调试,而宏定义不可以。

万事万物都有阴阳两面,内联函数也不外乎如此,使用inline函数,也要三思慎重。inline函数的缺点总结如下:

5.注意事项

了解了内联函数的优缺点,在使用内联函数时,我们也要注意以下几个事项和建议。

(2)如果函数体代码过长或者有多重循环语句,if或witch分支语句或递归时,不宜用内联。

// base.h class Base{ 
   protected:void fun();}; // base.cpp #include base.h inline void Base::fun(){ 
   } // derived.h #include base.h class Derived: public Base{ 
   public:void g();}; // derived.cpp void Derived::g(){ 
   fun();} // VC2010: error LNK2019: unresolved external symbol 

上面这种错误,就是因为内联函数 fun() 定义在编译单元 base.cpp 中,那么其他编译单元中调用fun()的地方将无法解析该符号,因为在编译单元 base.cpp 生成目标文件 base.obj 后,内联函数fun()已经被替换掉,编译器不会为 fun() 生成函数实体,链接器自然无法解析。所以如果一个 inline 函数会在多个源文件中被用到,那么必须把它定义在头文件中。

这里有个问题,当在头文件中定义内联函数,那么被多个源文件包含时,如果编译器因为 inline 函数不适合被内联时,拒绝将inline函数进行内联处理,那么多个源文件在编译生成目标文件后都将各自保留一份inline函数的实体,这个时候程序在链接阶段会出现重定义错误吗?答案是不会,原因是,链接器在链接的过程中,会删除多余的 inline 函数实体,只保留一份,所以不会报重定义错误,因此我们不需要使用 static 关键字去多余地修饰 inline 函数,即不必像下面这样。

// test.h static inline int max(int a,int b) { 
    return a>b?a:b; } 

原因是在类里定义时,这种函数会被编译器编译成内联函数,在类外定义的函数则不会。内联函数的好处是加快程序的运行速度,缺点是会增加程序的尺寸。比较推荐的写法是把一个经常要用的而且实现起来比较简单的小型函数放到类里去定义,大型函数最好还是放到类外定义。

可能存在疑问,类体内的成员函数被编译器内联处理,但并不是所有的成员函数都会被内联处理,比如包含递归的成员函数。但是实际测试,将包含递归的成员函数定义在类体内,被不同的源文件包含并不会报重定义错误,为什么会这样呢?请保持着疑问与好奇心,请继续往下看。

如果编译器发现被定义在类体内的成员函数无法被内联处理,那么在程序的链接过程中也不会出现函数重定义的错误。其原因是什么呢?其实很简单,类体内定义的成员函数即使不被内联处理,在链接时,链接器会对重复的成员函数实体进行冗余优化,只保留一份函数实体,也就不会出现函数重定义的错误了。

除了 inline 函数,C++编译器在很多时候都会产生重复的代码,比如模板(Templates)、虚函数表(Virtual Function Table)、类的默认成员函数(构造函数、析构函数和赋值运算符)等。以函数模板为例,在多个源文件中生成相同的实例,链接时不会出现函数重定义的错误,实际上是一个道理,因为链接器会对重复代码进行删除,只保留一份函数实体。

6.小结

可以将内联理解为 C++ 中对于函数专有的宏,对于 C 的函数宏的一种改进。对于常量宏,C++ 提供 const 替代;而对于函数宏,C++ 提供的方案则是 inline。C++ 的内联机制,既具备宏代码的效率,又增加了安全性,还可以自由操作类的数据成员,算是一个比较完美的解决方案。

上面的结论和观点,缺乏实践和权威资料支撑,难免存在错误,仅供参考学习,如果大家发现错误和需要改进的地方,请大家留言给予宝贵的建议。


参考文献

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

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

(0)
上一篇 2026年3月26日 下午2:54
下一篇 2026年3月26日 下午2:54


相关推荐

  • MBUS协议_协议解析

    MBUS协议_协议解析来自于我的163博客,一篇好好的技术文章,在163上居然提示不能显示,我2014年6月25日就翻译出来了,当时很多其他博客都是直接拷贝我的文章都能在网上发布。看了许多关于MBus协议的资料,感觉说的不具体、不完整、也不系统,本人准备结合一个具体的产品实现,从理论和实现上对MBus协议做一个详细的论述,如有不当之处,欢迎讨论。1介绍MBus(MeterB…

    2022年10月16日
    4
  • STM32之定时器配置

    STM32之定时器配置今天记录一下 stm32 定时器的学习 很多地方也不是很懂 只把初始化定时器的部分理解了一个大概 做一个单纯的记录吧 以后的学习中再深入理解一下 中断系统 NVIC 这一部分要明确中断优先级的概念 抢占优先级

    2026年3月20日
    1
  • 计算矩阵的欧式距离

    计算矩阵的欧式距离对于 kNN 算法 难点在于计算测试集中每一样本到训练集中每一样本的欧氏距离 即计算两个矩阵之间的欧氏距离 现就计算欧式距离提出三种方法 1 两层循环分别对训练集和测试集中的数据进行循环遍历 计算每两个样本之间的欧式距离 此算法没有经过任何优化 importnumpya 1 np array 1 2 3 4 5 6

    2026年3月16日
    2
  • python进阶(4)文件操作

    python进阶(4)文件操作文件操作文件操作主要包括对文件内容的读写操作,这些操作是通过文件对象实现的,通过文件对象可以读写文本文件和二进制文件open(file,mode='r',buffering=-

    2022年7月30日
    7
  • 即梦AI怎么用?🚀新手必看的详细教程来啦!

    即梦AI怎么用?🚀新手必看的详细教程来啦!

    2026年3月13日
    2
  • 2021.5.WIN7 旗舰 激活码【在线注册码/序列号/破解码】

    2021.5.WIN7 旗舰 激活码【在线注册码/序列号/破解码】,https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月18日
    89

发表回复

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

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