认识C++的内联函数
认识C++的内联函数
内联函数是C++中一种特殊的函数类型,它在编译阶段会被直接嵌入到调用它的地方,而不是像普通函数那样进行函数调用的流程。这种特性使得内联函数在提高执行效率的同时,还能保持代码的可读性。本文将详细介绍内联函数的概念、优势、适用场景以及使用限制。
内联函数是什么
首先我们要知道内联函数和其他的一般函数是有区别的,内联函数在编译阶段,编译器会尝试直接将函数的代码直接嵌入到调用它的地方(类似于#define进行宏替换的过程,只是不在同一时期),而不是像普通函数那样进行函数调用的流程(如入栈、跳转等操作)。在 C++ 中,使用inline
关键字来声明内联函数。
优势
- 提高执行效率:对于一些简单且频繁被调用的函数,避免了函数调用的开销(像建立栈帧、参数传递、返回值处理等过程的时间消耗),使得程序执行速度可能加快,代码执行起来更高效。比如一些简单的数学运算函数,像求两个数之和、差等函数,将其设为内联函数能优化性能。
- 保持代码可读性:它在形式上依然是函数的形式,与普通函数的编写、调用方式类似,相比于直接把代码写在调用处(宏定义展开那种方式,容易出现错误且可读性差),内联函数在保证代码逻辑清晰的同时,又能获得类似宏展开的性能提升效果。
并不是所有函数都可以设置为内联
针对一些函数被频繁调用或者逻辑较为复杂的函数(包含循环、条件、递归等)一般不适合进行内联修饰。否则会导致函数复杂度或代码膨胀:
- 函数复杂度限制:内联函数通常适用于简单短小的函数,因为编译器如果觉得函数体太复杂,即便声明为内联函数,也可能不会真正进行内联处理。例如一个包含大量循环、复杂逻辑判断的函数,编译器大概率不会按内联的方式处理它因为这就违背了内联的意义。
- 代码膨胀风险:如果过度使用内联函数,尤其是对于那些虽然简单但被大量调用的函数,可能会导致生成的可执行文件体积增大,因为函数代码在多处被复制嵌入代码片段过多,产生代码膨胀问题,进而影响程序的整体性能,所以要合理选择使用内联函数的场景。
内联函数的声明定义不能分离在两个文件中
我们知道,如果函数没有加inline
的话:它会在编译期间进行符号汇总,在汇编期间生成符号表,最后在链接的时候进行符号表的合并,这样的话,定义函数的文件和声明函数的文件都能够在符号表中找到对应的函数。即使声明和定义分离,后续在使用这个函数的时候也能找到这个函数的地址。
可是,如果函数加了inline
的话:并且声明和定义分离在两个文件中,只有定义函数的文件中能使用这个函数,声明函数的文件中却不能使用函数。这是因为加了inline
之后,定义函数的文件就不会将该函数放在符号表中,而是在编译阶段就直接将函数在调用的位置处进行展开了。后面在符号表的合并和重定位的时候,声明函数的文件也找不到该函数实际的地址了。所以这个时候,声明函数的文件中如果再使用这个函数的话,它是在符号表中找不到这个函数的,这个函数本身也就视作是不存在的,因此内联函数是不能进行分离定义在两个不同的文件当中的。如果要使用内联的话,就必须保证调用内联函数的文件和定义内联函数的文件是在同一个文件下的。
综上所述,内联函数声明和定义分离在不同文件中的话,定义函数的文件不会将函数和函数地址放在符号表中(调用处直接展开),声明函数的文件在使用该函数时会找不到该函数的地址,所以会发生链接错误。
本文原文来自CSDN