我知道在某些情况下,显式定义的内联函数将被编译器转换为带调用堆栈的常规函数。我怎么知道这是这种情况? (对于我的C ++代码)
BTW,在什么情况下编译器会将内联函数转换为常规函数?答案 0 :(得分:4)
您在可执行文件上运行nm
或otool
,如果您看到该函数的名称,则已定义该函数。这并不意味着它根本没有内联(编译器可能内联函数但也生成一个独立的函数体,因为例如一个函数指针指向它)。为此,您需要检查实际生成的汇编代码。
答案 1 :(得分:2)
关键字inline
并不意味着该函数将被内联(或不)。这意味着允许在同一程序的不同翻译单元中进行多个定义。编译器不会将内联转换为非内联,它将遵循标准中设置的规则,并且(几乎)正交地确定是否内联函数。
至于是否确定函数是否内联,保证的方法是检查生成的目标代码(或程序集)。检查是否存在函数的外联定义将无济于事,因为即使代码实际内联,许多编译器也会生成该外联定义。
答案 2 :(得分:0)
如果内联函数已经获取了它的地址(也就是说,你正在创建一个指向它的函数指针,或类似的东西),编译器将DEFINITELY产生一个常规函数。当然,如果函数是virtual
,它也必须作为独立函数存在,因为virtual
函数调用并不总是可以内联。
除此之外,它完全取决于编译器 - 它使用各种启发式方法,例如“功能有多大?”,“它被调用多少次?”,“有多少'增益'在那里来自内联吗?“如果一个函数被多次调用,并且非常大,它可能会作为独立函数保留。如果函数只被调用了几次,或者它很小,那么它就是内联的[假设编译器实际上是CAN内联它,当然 - 如上所述,它可能无法实现]。此外,几乎所有编译器都需要“看到”函数的源代码来内联函数,但GCC / G ++和MSVC都有“整个程序优化”的目的,旨在克服这个问题。
换句话说,您只能通过阅读生成的机器代码来“知道” - 在某些情况下,还可以启用扩展的“警告”或“注释”消息,告诉编译器为您提供有关“我没有内联函数Func1
,因为......在这里插入一些理由......“。