【C++】之内联函数(inline)

目录

一.概念

二.特性

三.类内成员函数具有内联属性

四.内联函数与宏函数的区别


首先声明: 因为inline函数需要支持调试, 在debug版本下内联函数一律都是call函数地址, 想要观察inline函数在调用处展开需要在release版本下观察

一.概念

用inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数可以提升程序运行的效率。

为何会有内联函数?

在C语言中,有#define宏这个概念,在宏内,是可以写函数的,我们称之为宏函数。内联函数可以看作是宏函数的升级版本,将宏函数的优点保留,将缺点去掉,这就是内联函数

inline int func()
{
	int a = 1, b = 2;
	return a + b;
}

int main()
{
	int ret = func();
	return 0;
}

二.特性

1.内联函数是一种以空间来换取时间的做法,省区调用函数的额外开销,内联函数会直接在函数调用处把原函数拷贝过来,所以如果函数代码很长或者很复杂,不适合转变为内联函数。

举例:假设一个函数有100行,整个程序需要调用这个函数1w次

不使用内联函数:整个程序代码量:程序代码+1w+100(行)

使用内联函数:整个程序代码量:程序代码+1w*100(行)

如果将这种大函数当作内联函数来使用的话,会使代码量暴增,空间消耗急剧增加!

2.inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体过大,编译器优化时会忽略掉内联。

也就是说当你给一个函数前面写上inline,此时这个函数确确实实拥有了内联属性,但这只是一个建议,编译器具体是否将这个函数在调用处展开,这个取决于编译器的优化,如果编译器认为你的inline函数过大,便不会展开,但是注意,这里仅仅只是不会当作内联函数去处理,而这个函数的内联属性还是存在的。(之后会有这方面的例子)

3.内联函数不能声明与定义分离,如果分离,必会发生链接错误。

因为编译器对于inline的处理,是将inline函数直接展开到调用处,从而inline函数这个函数地址就不需要放在符号表里面了。也就是说,当一个函数有了内联属性,函数地址就不会写入符号表,其他文件调用函数需要通过符号表中的函数地址来匹配从而找到函数定义,这时就找不到了,由于链接不到,结果就会引发链接错误

三.类内成员函数具有内联属性

类内的成员函数,如果这个成员函数定义在类内(注意是定义而不是声明),编译器可能会将其当成内联函数处理。

一但这个类内的成员函数的声明与定义分离开了,就不会具有内联属性。

这样的好处是什么呢?

答:可以实现将小函数直接定义在类内!这样由于编译器会将其当作为内联函数,如果把类写在一个头文件下,他的成员函数的定义也是在头文件下的,此时如果多个.cpp文件都需要引用这个头文件,那么这些成员函数就会在许多个.cpp中都定义了一次,由于这个定义的函数编译器把他当作为内联函数,函数地址不会写入符号表,就不会发生成员函数之间的冲突

看到了吧,上面这个图,打印的是头文件里定义的函数,说明在引用头文件后,编译器在编译时的预处理阶段将头文件展开后,.h文件的成员函数定义就被展开到了这个main.cpp中,然后又因为成员函数有内联属性,所以不会把func函数地址写入符号表,.h定义的func和func.cpp定义的func就不会冲突,然后main.cpp直接把头文件的func函数拷贝到了调用的地方,打印出了hello inline

上图也可以说明,上面inline特性的第2点,如果把这个成员函数写的非常复杂,仍然不会发生冲突,因为虽然函数很大,编译器优化的时候没有在调用处展开,但是这个成员函数是在类内定义的!所以函数地址不会写入符号表,直接调用展开的头文件定义的func,最终打印hello inline

上图展示了,将成员函数分开写,直接报错!成员函数定义与声明一但分离,立即失去内联属性,函数地址全部写入符号表,符号表内存在两个func1,且这俩func1一模一样无法发生函数重载,最终结果:冲突报错,这属于链接错误,在链接的时候编译器不知道链接具体哪一个

四.内联函数与宏函数的区别

宏的优缺点:

       优点:1.提高代码的复用性

                  2.提高性能,减少创建/销毁栈帧的消耗

       缺点:1.不方便调试

                  2.代码可读性差,容易出错

                  3.没有安全类型检查

内联函数与宏函数的区别:

1. 内联函数可以调试,而宏定义不可以。

2. 编译器会对内联函数作语法检查,而宏定义不会。

3. 内联函数可以访问类的成员变量,宏定义不能。

4. 在类中声名同时定义的成员函数,拥有内联属性。

5. 内联函数是函数,宏不是函数。

6. 内联函数将代码直接插入调用处,减少普通函数调用资源,宏是在代码调用处不加任何验证的简单替换。

内联函数的出现,避免了宏函数的缺点,同时拥有宏函数的优点。

在C++中,能使用const、inline、enum来代替宏,就不使用宏。

这一篇详细讲述了inline以及inline代替宏函数,在下一篇就来叙述一下C++中,const的用法

C++和C语言中的const有什么区别,如何用const来代替#define定义的宏常量!

  • 24
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值