1、inline的作用
在C++中,为了解决一些频繁调用的小函数大量消耗栈内存问题,特别的引入了inline修饰符,表示为内联函数。
栈空间是指防止程序局部数据的内存空间。在系统下,栈空间是有限的,如果频繁大量的使用就会造成因栈空间不足而导致程序出错的问题。
在程序编译时,编译器将程序中出现的内联函数调用表达式用内联函数的函数体进行替代,类似于宏展开。如:
int min ( int v1, int v2)
{
return (v1< v2 ? v1: v2);
}
//代码编写时,是直接按照函数名进行调用
int minval2 = min(i,j);
//实际编译之后,把函数体内部代码进行替换
int minval2 = i < j ? v1: v2;
2、内联函数的好处
最大的好处当然是提高函数的执行效率,内联函数实际上使用空间换取时间的做法,以代码复制为代价,省去了函数调用的开销,从而提升执行效率。下面总结一下其他好处:
- 如果一段代码包含min()的调用,那阅读这样的代码并解释其含义比读一个条件操作符的实例,可读性要强很多。
- 改变一个局部化的实现比更改一个应用中的300个出现要容易的多。
- 语义是统一的,每个测试都能保证相同的实现方式。
- 函数可以被重用,不必为其它的应用重写代码。
3、inline的使用
inline有这么大的好处,但是使用也有相应的规则:
- inline 只适用于函数体内代码简单的函数,不能包含复杂的结构控制语句,如while、switch,并且内联函数本身不能是递归函数
- inline函数仅仅是对编译器的建议,最后能否真正的内联,决定在编译器。
- inline关键字必须与函数定义体放在一起才能使函数成为内联。仅将inline放在函数声明前,不起任何作用。
- 建议:因为上一条的原因,最好将内联函数的定义放在头文件里。
4、类与inline函数
定义在类中的成员函数缺省都是内联的。如果在类中未给出成员函数定义,而又想内联该函数的话,需要在类外加上inline。如:
class myclass
{
public:
int Add(int x, int y ){ return x+y; }; //自动成为内联函数
}
将成员函数的定义放在类声明之中,虽然书写方便,但不是一种良好的编程风格,上面可改为:
class myclass
{
public:
int Add(int x, int y);
};
//实现文件
inline int A::Foo(int x, int y ){ return x+y; };
虽然理论是这样的,但是在VS中使用这样的类成员函数,链接器会报错。所以最好还是写在头文件中。
virtual函数不能是inline的,virtual意味着知道运行期才确定调用哪个函数,而inline意味着执行前,先将调用动作替换为被调用函数的本体。
5、inline和宏的区别
通过前面的介绍,你可能也发现了,inline和宏很相似,但是他们有什么差别吗?其实inline就是用来替换宏定义的。下面就对两者就行整理:
相同点:
- 通过替换或展开,没有了函数调用相关的操作,提高了效率
不同点:
- 宏定义容易产生二意形,inline函数不会
- 宏定义是在预处理阶段进行的替换,inline函数是在编译阶段进行替换
- 宏定义只是简单的替换,而inline是函数,编译器会进行严格的类型和作用域检查,保证调用正确。消除了它的隐患和局限性。
- 宏定义不能用于类成员,没有this指针的位置,而inline可以用于类成员。
6、总结
内联函数并不是一个增强性能的灵丹妙药。只有当函数非常短小的时候它才能得到我们想要的效果。但是,如果函数并不是很短而且很多地方被调用的话,那么将会使得可执行程序体积增大。所以如果内联函数不能增强性能,就避免使用它!
再提一点:在release调试的时候,inline函数断点是无效的,毕竟你相当于在一个不存在的函数内设断点。在debug版本下没有问题,因为debug版本程序禁止发生inlining。
感谢大家,我是假装很努力的YoungYangD(小羊)。
参考资料:
https://blog.csdn.net/hejjunlin/article/details/78239277
https://www.cnblogs.com/fnlingnzb-learner/p/6423917.html