内联函数(inline)
简介:
用inline修饰的函数叫内联函数,编译时C++编译器会在调用的地方站开内联函数,这样调用函数就不需要创建栈帧了,可以提高效率。
内联函数与宏函数:C++中的内联函数与C中的宏函数很相似,都是直接在预处理时展开函数,将函数直接替换到调用位置,不额外创建栈帧。但内联函数相比宏函数做了优化。内联函数本意上是要代替宏,因为太复杂的宏替换时容易出错。
使用说明:
1.inline的建议
inline 实际上对于编译器来说只是一个建议,在代码行数少的时候编译器会进行展开,而代码行数较多的时候(不同编译器可能对于多的标准不同),编译器不会展开内联函数,因为展开会大大增加代码量,会导致在预处理的步骤产生过多的指令,降低效率。
比如递归函数或者代码行数较多的函数加上inline,编译器也不会展开。
注意:VS编译器debug版本下默认不展开inline,方便调试。
下面是汇编指令,其中call 的那一行就是为函数创建了栈帧,是函数未展开在程序中的情况,如果是inline函数并且符合展开要求,则不会出现call这一行创建栈帧。
2.inline的不分离
inline不建议声明和定义分离到两个文件,分离会导致链接错误。
这里想要理解需要懂得东西有些多,如下:
编译和链接(简单来说)
编译分为三个阶段:预处理、编译、汇编。
预处理:进行宏的展开、条件编译指令、去注释、头文件展开等操作。
编译:进行词法分析、语法分析、语义分析、优化、生成汇编代码
汇编:将汇编代码转换成机器可执行指令。
在编译的语义分析阶段,会创建并更新符号表。(符号表:一种数据结构,用来存储程序中所有标识符的相关信息)标识符:如变量名、函数名等。
链接时,声明用来告诉编译器实体的存在,定义用来提供实体的实际代码或数据。(实体指C++中的对象,可以是变量、函数、类等)
定义和声明
声明指告诉编译器一个标识符(如变量名或函数名)的名称和类型,但不分配存储空间。只要是一致的,就可以多次出现。
变量和函数声明:只声明,不分配内存
定义指为实体(变量、函数、类等)提供具体实现或储存分配。
注意:初始化不等同于定义,有时不初始化也可以是定义。
理解
如果只在源文件或头文件中定义的话,编译器一般认为inline函数在预处理时会替换,所以在编译的语义分析时不会吧把nline函数的标识符相关信息放到符号表里,就不会创建函数栈帧来调用inline函数。
所以inline函数的声明和定义的不分离其实就是因为,如果声明在源文件中,定义在头文件中,在预处理阶段头文件展开在源文件中后,同时因为它是内联函数,直接也被展开在程序中了,在之后的链接时声明虽然提供了这个内联函数的地址,但找不到这个内联函数的实体,所以链接错误。QAQ
嗯,建议将inline函数的定义直接放在头文件中,不用在源文件中声明。要使用包含头文件就行。
标签:函数,C++,语法,编译,编译器,内联,inline,展开 From: https://blog.csdn.net/2401_86702190/article/details/143701111