2

我知道在某些情况下,显式定义的内联函数将通过编译器调用堆栈转换为常规函数。我怎么知道是这种情况?(对于我的 C++ 代码)

顺便说一句,在什么情况下编译器会将内联函数转换为常规函数?

4

3 回答 3

4

您在可执行文件上运行nmotool,如果您看到函数的名称,则它已被定义。这并不意味着它根本没有被内联(编译器可能会内联一个函数,但也会生成一个独立的函数体,因为例如分配了一个函数指针给它)。为此,您需要检查实际生成的汇编代码。

于 2013-07-20T18:53:37.910 回答
2

关键字inline并不意味着该函数将被内联(或不被内联)。这意味着允许在同一程序的不同翻译单元中进行多个定义。编译器不会将内联转换为非内联,它将遵循标准中设置的规则,并且(几乎)正交地确定是否内联您的函数。

至于是否确定一个函数是否被内联,保证这样做的方法是检查生成的目标代码(或程序集)。检查函数是否存在外联定义无济于事,因为即使代码实际上是内联的,许多编译器也会生成该外联定义。

于 2013-07-20T18:55:11.357 回答
0

如果内联函数获取了它的地址,编译器肯定会生成一个常规函数(也就是说,你正在创建一个指向它的函数指针,或类似的东西)。当然,如果函数是virtual,它也必须作为独立函数存在,因为virtual函数调用并不总是可以内联。

除此之外,这完全取决于编译器——它使用各种启发式方法,例如“函数有多大?”、“它被调用了多少次?”、“内联它有多少‘增益’ ?”。如果一个函数被多次调用,并且非常大,它可能会被保留为一个独立的函数。如果该函数只被调用了几次,或者它很小,那么它就是内联的[假设编译器实际上可以内联它,当然——如上所述,它可能无法内联]。此外,几乎所有编译器都需要“查看”函数的源代码来内联函数,但 GCC/G++ 和 MSVC 都具有旨在克服此问题的“整个程序优化”的选项。

换句话说,您只能通过阅读生成的机器代码来“知道”——在某些情况下,您还可以启用扩展的“警告”或“注释”消息,告诉编译器向您提供有关“我没有内联函数Func1,因为...在此处插入一些原因...”。

于 2013-07-20T18:58:11.363 回答