【问题标题】:when does the compiler necessarily not make a function marked inline as inline编译器何时不必将函数标记为 inline 为 inline
【发布时间】:2013-04-15 16:53:44
【问题描述】:

编译器什么时候不一定要把内联标记为内联的函数?

【问题讨论】:

  • 对于现代编译器,这可能不是二元选择。众所周知,现代编译器会拆分函数,并且内联的决定可以是分开的。例如。由于假定异常很少见,编译器只能内联函数的非异常部分。

标签: c++ performance inline


【解决方案1】:

最明显的是,当您使用指向函数的指针时,它不能内联该函数。如果您传递指针并且(可能稍后)决定通过指针调用函数,编译器必须生成函数的非内联版本。当然,如果直接调用函数,编译器可能仍然内联它。而且编译器也可以随意不内联函数。

【讨论】:

  • +1 这是 functor-vs-funcptr 提供的东西的根本原因,可以更理想地适用于给定函子的内联扩展。可以在in this question 找到关于函子及其优势的精彩问答。
【解决方案2】:

使用inline 关键字只是对编译器的提示,您建议在使用的地方内联扩展它。然而,在预测 L1 和 L2 缓存以及分支预测管道等高级 CPU 功能可能对性能产生影响时,编译器比您以往任何时候都智能得多。如果编译器决定内联函数会使代码变慢,或者不可接受地变大,它就不会内联它。或者,如果它只是因为语法依赖而无法实现,例如其他代码使用函数指针进行回调,或者像在动态/静态代码库中那样将函数导出到外部。

更多解释请参见here

【讨论】:

  • 我认为这与缓存大小没有太大关系。这主要与本地人的数量和有效的寄存器分配有关。
  • 重要的说 - 没有办法知道它是否会种植内联
  • @Infested - 一些编译器具有强制内联的内在函数
  • 缓存大小肯定是相关的,是否内联函数可能会导致 CPU 在其缓存策略中做出不同的决定。诚然,这不是最相关的因素,但它是编译器会尝试检查的众多事情之一。
  • @ddriver 你是对的,但不鼓励使用这些知识编写,因为并非所有编译器都这样做。
【解决方案3】:

如果问题是编译器无法以任何方式内联函数,那么有几个答案。

定义后,如果函数是递归的,其递归级别取决于参数,而不是尾递归,则不能内联(在编译时不可能知道函数的迭代次数)。通常,不显示尾递归的递归函数不会被内联(即使在编译器可以推断出递归步骤数的情况下)。

在看不到指针初始化的上下文中通过指针使用时。

如果问题不是什么时候保证不被内联,而是什么东西可以让编译器避免内联,还有一些其他的。例如,函数的复杂性和大小,它是否有循环,它已经在做的内联级别(f调用g调用h调用i......所有这些都可能被内联,但编译器倾向于放弃如果通话次数足够多)....还有其他的。您可以尝试从您的编译器供应商那里了解他们运行什么类型的启发式方法来确定何时内联。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多