If I use inline functions, does the memory usage increase?
8 回答
内联函数会影响两种内存使用情况:
代码大小——一般来说,内联代码会增加加载程序所使用的内存量。这是因为生成代码的多个副本会散布在您的程序周围。但是,这并不总是正确的——如果您的内联函数只使用一次,则几乎没有变化,如果内联函数非常小,您可以通过消除函数调用开销来净减少代码大小。此外,优化器可能会减小函数的大小,该优化器能够删除未在特定内联调用中使用的代码。
堆栈使用——如果你的内联函数有很多局部变量,那么你可能会使用更多的堆栈空间。在 C 语言中,编译器通常在函数进入时为函数分配堆栈空间。这必须足够大以容纳所有未存储在寄存器中的局部变量。如果您离线调用一个函数,则该函数的堆栈将一直使用,直到它返回,当它再次被释放时。如果您内联该函数,那么该堆栈空间将在 uber 函数的整个生命周期中一直使用。
内联不会影响堆使用,因为内联代码会发生与非内联版本相同的分配和释放。
还有一点你需要考虑:
使用内联函数,编译器能够看到调用者的变量将在哪里用作被调用者的变量。编译器可以根据该知识优化出(通常这实际上是许多可以省略的汇编程序行。注意所谓的“别名问题”)冗余代码。所以你的“代码膨胀”通常不是那么大,特别是如果你有更小的函数,它甚至可以减少上面吉姆所说的膨胀。
有人提出了一个很好的观点:最好让编译器决定它是否内联有问题的函数,因为它比你更了解它生成的代码。
在一般情况下,这确实是无法回答的。
首先,您通常无法控制内联。即使您将函数标记为内联,它实际上仍然取决于编译器,它实际上会执行内联(这只是一个提示)。
编译器会尽最大努力优化代码;使用内联只是这样做的一种工具。因此内联短函数将使代码更小(因为您不需要为调用设置参数或检索返回值。但即使使用长函数,答案也不是绝对的。
如果编译器决定内联一个长函数,那么您会认为代码会变得更长。但通常情况并非如此;因为这为编译器提供了额外的机会来应用其他可能使代码更小的优化技术。如果编译器分析发现生成的代码膨胀对代码有害,则不会进行内联。
基本上,编译器会进行分析并决定最佳行动方案。
结论。别担心。编译器比你聪明,并且会做正确的事情。
取决于功能。简单的单行代码可以减少内存,因为不需要设置和清理调用堆栈,也不需要进行函数调用。如果函数大于调用函数所需的开销,那么它当然会使代码膨胀。
内联函数肯定会增加最终可执行文件(或二进制文件)的大小,因为无论您在哪里调用它们,它们都会被“复制粘贴”。
有时会发生函数分散在程序中的情况。在这种情况下,函数调用会导致程序跳转到函数的地址并在函数调用终止时返回。这会占用一些宝贵的时间。
使用内联函数可以解决上述问题。这会导致编译器直接从源代码调用代码。没有为内联函数代码创建新的内存指令集。
虽然 c++ 中的内联声明是自由的,并且在声明中定义函数时自动发生,但在 c 中它受到以下规则的限制::
在 C 中,任何具有内部链接的函数都可以声明为内联,但具有外部链接的函数对内联有限制。
如果在函数声明中使用了 inline 关键字,那么函数定义应该出现在同一个翻译单元中。
内联数据类型函数名称(参数)
此代码的运行速度比非内联函数快 30%,其余代码取决于处理器速度。
现在是战略部分。您可以随意使用内联函数,但请记住,内联函数的执行时间要少得多,但它们在运行时会占用很高的内存。此外,如果内联声明的代码与代码大小相比异常大,编译器始终可以选择忽略您的内联声明。
内联声明虽然破坏了求值顺序,但并不使函数内部化。该功能仍然是外部的。
在一般情况下,您的程序会变得更大(但我相信也有例外)。运行时内存消耗可能会下降,但不会下降太多。
你问来干什么?通常,你让编译器决定一个函数是否应该被内联;考虑到函数的大小和复杂性,它通常可以做出更好的调用。
函数调用需要多个处理器指令。
您通常需要为函数的每个参数提供一条 PUSH 指令,一条调用该函数的 CALL 指令,并且通常需要另一条在函数调用后清理堆栈的指令。
此外,函数可能会修改处理器的寄存器,因此调用函数可能需要更多指令来保留寄存器或重新加载否则仍会在寄存器中的值。
所以如果你调用的函数只有几条指令,内联它可以节省内存并运行得更快。
也就是说,内联适用于您的分析器告诉您应该这样做的时候。