inline那些事

本文详细介绍了内联函数的概念、如何在类中使用、与普通函数、宏定义和静态函数的区别,以及内联函数的优点(如减少调用开销)和缺点(如代码膨胀)。强调了内联函数的适用场景和注意事项,指出内联函数并非总是提高效率,而是取决于具体函数特性及编译器优化。
摘要由CSDN通过智能技术生成

1. 内联基本概念

内联关键字 inline,用于函数内联,关键字inline需要添加在函数定义的地方,在声明的地方添加inline不生效;当函数功能简单,使用频率高时,为了提高效率,可以用inline直接将函数的代码嵌入到程序中。但需要注意的是:

  1. inline是一种以空间换时间的做法,可以省去调用函数额外开销,但当函数体的代码过长或者是递归函数,即使是加上inline关键字,也不会在调用点以内联展开该函数。
  2. inline对编译器而言,仅仅只是一个建议,编译器会自动优化。
  3. inline不建议声明和分离,分离会导致链接错误,因为inline被展开,就没有函数的地址了,链接就会找不到。

2. 类中内联

头文件中声明方法

#include <iostream>

using namespace std;

class Person
{
public:
	//类中已经定义了的函数为隐式内联函数
	int foo(int x, int y)//只要定义了,就是内联!
	{
		return x - y;
	}
	//如果函数只有声明,还想成为内联函数,必须在实现的地方加inline
	void f1(int x);//声明后,想成为内联,需要在定义的地方加inline
};

实现文件中定义内联函数

//类的成员函数:定义处加inline关键字
inline void Person::f1(int x)
{
	return;
}

//非类中成员函数内联
int fff(int x, int y);//非类成员函数声明
inline int fff(int x, int y)//非类成员函数定义,定义前加inline
{
	return x + y;
}

编译器对inline函数的处理步骤
将inline函数体复制到inline函数的调用处;
为所用到的inline函数中的局部变量分配内存空间;
将inline函数的输入参数和返回值映射到调用方法的局部变量空间中;
如果inline函数有多个返回点,将其转变为inline函数代码末尾的分支(使用goto)

注意:内联能提高函数效率,但并不是所有函数都定义成内联,内联是以代码膨胀(复制)为代价,仅仅省区了函数调用的开销,从而提高函数的执行效率。

1、如果执行函数体代码的时间相比于函数调用的开销较大,那么整体效率更低;

2、如果函数体内出现循环,那么执行代码所需的时间要比函数调用的开销大;

3. 内联函数和宏定义比较

  • inline函数相对宏函数有如下优点
    (1)内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。
    (2)内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。
    (3)在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。
    (4)内联函数在运行时可调试,而宏定义不可以。

  • 内联函数的缺点:
    (1)代码膨胀。
    inline函数带来的运行效率是典型的以空间换时间的做法。
    (2)inline 函数无法随着函数库升级而升级。
    如果f是函数库中的一个inline函数,使用它的用户会将f函数实体编译到他们的程序中。
    (3)是否内联,程序员不可控。
    inline函数只是对编译器的建议,是否对函数内联,决定权在于编译器。

4. 小结

  • inline函数与普通函数的比较:

1、普通函数有开栈和清栈,inline函数无开栈和清栈。
2、当执行开销(代码小)< 调用开销(开栈)时,建议用inline
3、当执行开销(代码小)> 调用开销(开栈)时,不建议使用inline
4、普通函数在调用过程中,会对寄存器中内容进行上下文切换(push和pop操作),而内联函数则不需要,所以普通函数相比内联函数,耗时要多一些。
5、当函数使用次数比较多的时候,内联函数在每个调用的地方都会被展开,所以导致固件大小会变大,同一段代码会多次重复出现在固件中。而普通函数则没有此问题,不管调用的函数的次数多少,函数在固件中均只占用一处,空间利用率较高。

  • inline和static 的区别:

1、内联函数没有开栈清栈的开销,static函数有;
2、inline编译阶段代码展开导致函数本文件可见,而static是因为符号属性为local本文件可见。

  • inline和宏的区别:

1、inline编译时处理有类型检查,安全检查和语法判断等功能,宏预编译时处理无类型检查和安全检查,只是简单的替换
2、宏无法调试,而内联可以进行调试。
3、内联比宏更加安全,是一种更加安全的宏
4、内联函数在编译时展开,带参的宏在预编译时展开
5、内联函数直接嵌入到目标函数代码中,带参的宏是简单的作文本替换
6、相同点: 两个都代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高运行速度。

注意:

1、内联函数的声明和定义一般全部写在头文件中。
2、只在release版本生效。
3、内联只是程序员给编译器的一个建议,循环、递归、switch一定不会出现inline。
4、inline基于实现,不是基于声明,即在声明点无效(先声明后内联)。
5、内联函数相比普通函数,少了上下文切换的步骤所以执行会更快一些。
6、内联函数被多次调用,会使固件大小膨胀,内联函数的高速是以空间来换时间。
7、如果函数内容太过于复杂,编译器会忽略inline关键字,把他当成普通函数来处理。

  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值