对于那些回答的人来说,这应该很容易。这个问题有一个合乎逻辑的答案,但我想要问一下验证。
我对程序流程如何工作的理解很简单。函数及其相关指令位于存储器中的某个点。内存中的此位置是用于存储此类指令的单个位置。调用时,该函数的第一条指令的位置存储在程序流程中。该内存指针指示CPU在内存中的位置查找所需功能的指令。跳转到该位置并执行指令后,恢复正常的程序流程并且CPU跳回原始地址指令所在的位置以继续执行连续指令。
据我了解,内联函数会直接粘贴到调用它们的位置。因此,当写入源文件并定义内联函数时,实际上在内存中存在多个位置,此函数的指令集位于该位置(即它的确切位置)。那么,也就是说内存中的source
位置与非内联函数的位置相似?
此外,在编译过程中,编译器是否只是将内联函数准确地粘贴到调用的位置,并使用传递给它的参数删除/替换函数定义的任意参数名称?
答案 0 :(得分:4)
我的理解是
inline
函数被粘贴到调用它们的位置。
这取决于。即使函数是inline
,它也可能实际上没有被编译器内联。
那么,那就是说内存中没有类似于非内联函数的源位置?
这取决于函数的内联方式。如果在翻译单元中有4个对inline
函数的调用,编译器可能会决定内联其中一个是正常的,其余调用应该使用常规函数调用。所以在这种情况下,有一个“源”位置和一个内联位置。
此外,在编译过程中,编译器是否只是将内联函数准确地粘贴到调用的位置,并使用传递给它的参数删除/替换函数定义的任意参数名称?
inline
d函数必须与普通函数调用具有相同的含义。
答案 1 :(得分:3)
这几乎就像你在想的那样。 首先 - 它取决于语言/编译器。在C和GCC或MSVCC中,如果你告诉该函数是" inline"功能它并不意味着它将被内联!这取决于编译器及其实现,你的内联关键字/ pragma只是一个提示。
如果函数被标记为" inline"而不是粘贴在原始呼叫的所有地方但是......如果你正在编译一个库(静态或动态),它不会被删除。但是如果编译器决定内联它,它实际上粘贴了代码,并优化了调用。
顺便说一下。在Haskell(GHC)" inline" pragma不仅是一个提示,但你可以肯定,编译器将执行内联过程。就个人而言,我希望有一个C ++编译器,它将真正内联我告诉他的每个函数:)
答案 2 :(得分:2)
我的理解与你的理解相符。内联编译将删除该函数,并将其替换为该函数中的命令。任何参数都与传递给它们的值内联替换。正如你所说 - 没有跳转执行,没有函数添加到调用堆栈。
答案 3 :(得分:2)
编译器可以自由选择内联声明的函数是否应该是内联的。在内衬时,会有诸如此类的好处,
修改强> 何时使用内嵌
#define
。 (宏扩展是在每个处理时间内完成的。编译器完全不在图片中。但是对于内联函数,编译器在图片中,它可以进行错误检查......)答案 4 :(得分:1)
来自open-std.org的ISO/IEC 9899:TC2第112页告诉我们:
使用
inline
函数说明符声明的函数是内联函数 功能......制作功能 内联函数建议对函数的调用速度最快 (118)这些建议有效的程度如下 的实现定义强>(119)
该部分的脚注告诉我们:
(118)通过使用,例如,通常的函数调用的替代 机制,例如''内联替换''。 内联替换不是 文本替换,也不会创建新功能。因此, 例如,在体内使用的宏的扩展 函数使用函数体所具有的定义 出现,而不是调用函数的位置;和标识符 在身体发生的范围内的声明。 同样, 无论内联数量多少,函数都有一个地址 除外部定义外发生的定义。
(119)例如,实现可能永远不会内联执行 替换,或者可能只对调用进行内联替换 内联声明的范围。
我为我认为的部分添加了粗体字,或者纠正了对inline
的理解。
如果您想强制或希望inline
的特定行为,我建议您咨询您的编译器实现说明。关于(非)文本替换和单一地址的小问题很有意思。