C++ 内联函数时的编译器限制

C++ 内联函数时的编译器限制,c++,inline,C++,Inline,我知道,在向类成员函数添加inline关键字后,如果“函数不复杂”或函数体中有“许多语句”,编译器将决定内联 什么被认为是“很多声明” 如果隐式或显式获取函数的地址,编译器也无法执行内联。有人能解释这一点吗 因为内联只是一个建议,我如何测试哪些函数没有内联 关于编译器何时可以内联签出此线程的问题: 编译器是否内联生成代码取决于 编译器。大多数现代编译器将生成 任何不是递归内联的 这完全是错误的。当地址被记录下来时 编译器必须为地址生成一个越行副本,但是 这并不能阻止它在函数运行时内联 打电话来

我知道,在向类成员函数添加inline关键字后,如果“函数不复杂”或函数体中有“许多语句”,编译器将决定内联

  • 什么被认为是“很多声明”

  • 如果隐式或显式获取函数的地址,编译器也无法执行内联。有人能解释这一点吗

  • 因为内联只是一个建议,我如何测试哪些函数没有内联


  • 关于编译器何时可以内联签出此线程的问题:

  • 编译器是否内联生成代码取决于 编译器。大多数现代编译器将生成 任何不是递归内联的

  • 这完全是错误的。当地址被记录下来时 编译器必须为地址生成一个越行副本,但是 这并不能阻止它在函数运行时内联 打电话来

  • 你没有

  • 这完全取决于编译器;这可能取决于优化设置、目标体系结构的特性(例如,函数调用的成本与由于代码大小增加而导致的缓存未命中的潜在成本),以及函数在特定调用站点与其余代码的集成程度

  • 如果一个函数总是内联的,那么它本身就不再是一个函数,因为它的指令直接放在调用站点上,其余的调用方代码都放在调用站点上;由于这个原因,这样的函数不再有地址,因为它与调用者混合在一起。但是,当您请求函数地址时,通常会发生的情况是,编译器将在其最喜欢的位置内联函数,但仍然将其作为“常规函数”发出,并通过函数指针使用其地址

  • 您可以反汇编生成的可执行文件,或者要求编译器发出程序集,而不是构建完成的可执行文件(使用
    gcc
    这是
    -s
    选项),并手动检查它。不过,请注意,检查优化的二进制文件并不是一件小事——因为内联代码与调用者代码混合在一起,所以可能很难准确地找到内联函数的位置,同时您还可能找到函数的非内联副本,以便通过函数指针使用(如上所述)

  • 完全由编译器设计者决定使用何种启发式来决定是否内联函数调用。希望它是基于生成的代码大小,而不是“语句”的数量,这是一个完全没有意义的度量。希望它还包括对性能增益的估计,以衡量代码大小的任何增加

  • 如果获取了地址,那么必须有一个函数的非内联实例,这样才能获取地址。但是,如果编译器决定对函数的任何调用都应该内联,则这不会阻止对函数的任何调用内联

  • 您可以反汇编生成的代码以查看是否存在函数调用。如果调用函数很大,或者调用函数本身内联到另一个函数中,那么这可能会很棘手。大多数编译器都有(非标准)强制内联的方法;但是,只有在您确信自己比编译器更了解并且有度量来证明这一点的情况下,才可以使用它