【问题标题】:What is the difference between macro & inline function with respect to execution speed?在执行速度方面,宏和内联函数有什么区别?
【发布时间】:2011-01-21 16:57:46
【问题描述】:

编译器如何处理内联函数而不是宏以减少执行时间?

【问题讨论】:

  • 这是一个你不应该关心的过早优化。由于很多原因,函数更安全。此外,只有当编译器认为这是一个好主意时,函数才会被内联(因为通常人类选择内联现在是错误的选择(或者可能在函数被维护后稍后))。编译器的工作就是让东西变得快速(当你尝试过早地优化东西时,你只会妨碍编译器完成它的工作)。
  • 您能解释一下什么是过早优化吗?
  • "过早优化" 您正在尝试通过应用专门的技术来优化代码。而不是尽可能清晰简洁地编写代码。在您完成程序并对不同部分进行计时以找到瓶颈之前,通常没有必要考虑这些优化。编译器已经进行了这种优化的事实是对这种优化的又一次打击,因为人类永远无法击败编译器(从长远来看)。
  • @Martin York 我希望所有 SO 都会阅读您的评论。 “过早的优化”引用在这里被经常抛出。对明显的可扩展性和可维护性问题进行良好的规划与担心不可预测的事情之间是有区别的。我敢肯定,在这种情况下,您对这个短语的使用恰到好处,很好地表达了 Knuth 的意思。

标签: c++ inline


【解决方案1】:

如果这样做会更快,编译器也可以不内联函数,而编译器不能不内联宏。此外,内联函数比宏更安全。

【讨论】:

    【解决方案2】:

    内联函数与宏非常相似,因为它们都是在编译时扩展的,但宏由预处理器扩展,而内联函数由编译器解析。

    【讨论】:

      【解决方案3】:

      这里要注意的最重要的一点是,宏是由预处理器完成的纯文本替换。编译器(在预处理步骤之后)不知道也不关心宏是什么。

      例子:

      //this:
      #define PRINT(s) std::cout << s;
      
      int main(int, char**)
      {
        PRINT("hello world")
        return 0;
      }
      
      //Will have identical codegen(in the same compiler version of course) to this:
      
      int main(int, char**)
      {
        std::cout << "hello world";
        return 0;
      }
      

      然而,对于内联函数,编译器知道对函数的调用何时被内联,并且它有更多关于它使用的上下文信息。正如其他人所提到的,这也意味着这是一个请求。如果编译器认为内联函数更有害,那么它会将其保留为常规函数调用。与宏相比,编译器在使用宏时不会有关于代码重复的信息。

      总而言之,如果您的代码可以使用内联函数,那么请使用它而不是宏。通过提供更多信息,您正在帮助编译器改进您的代码。

      【讨论】:

        【解决方案4】:

        而且,MACROS 也无法访问类成员变量。它不了解范围。在这里,内联函数就派上用场了。

        【讨论】:

          【解决方案5】:

          应该没有速度差异(假设合理的小代码),因为它们都会被编译到它们被使用/调用的地方。使用函数只是更好的做法,因为宏可以做一些不可预见的事情。

          【讨论】:

          • 值得注意的是,将函数标记为内联并不能保证它会是 - 它是“请求”而不是指令。在这种情况下,会有(小)函数调用开销。完全同意优先使用它们而不是宏 - 您可以在参数列表中获得类型安全和更少的副作用
          • @Kev:但实际上内联也是有代价的。如果函数很大,这将导致更多的页面错误(因为程序会更大),因为程序加载会导致执行速度变慢。因此,您必须将函数调用的成本与额外的页面错误(以及其他一百万件事)的成本相比较。因此内联并不一定会使代码更快。
          • @Martin York 这不是关于是否内联函数的讨论。是使用宏还是函数。如果两者都做同样的事情,因此大小相同,那么使用该函数的最坏情况将与使用宏的大小相同。
          • @Martin。你是绝对正确的,但我实际上并没有说它会更快。我的评论主要是警告内联函数实际上可能没有内联在生成的代码中。对于您关于额外代码的论点,这当然同样适用于宏。底线是,如果您关心任何与性能相关的事情,请衡量选项
          • @gamernb:你没有抓住重点。宏不能成为函数,因此编译器必须将它们内联。函数可以根据编译器的选择进行内联。如果您从编译器中删除选择,您最终会得到较慢的代码(编译器最终总是会做出一个好的选择,所以不要从编译器那里拿走选择)。
          【解决方案6】:

          内联函数遵循对普通函数强制执行的所有类型安全协议。

          内联函数使用与任何其他函数相同的语法来指定,除了它们在函数声明中包含 inline 关键字。

          作为参数传递给内联函数的表达式只计算一次。在某些情况下,作为参数传递给宏的表达式可以被多次计算。

          要记住的另一件事是宏在预编译时扩展,因此您不能将它们用于调试。然而,对于内联函数,情况并非如此。

          作用域在宏的情况下是全局的,局部作用域可以应用于内联函数。

          【讨论】:

            【解决方案7】:
                     Inline Function                                        Macros
            
            1. 内联函数被编译器解析 | 1. 宏由预处理器处理。
            2. 内联函数可以写在里面 | 2.里面不能写宏。 班上。 |
            3. 内联执行严格类型检查 | 3. 宏不执行严格的检查。
            4. 内联函数由关键字进行。 | 4. 宏在哪里由#include 进行 | ,定义。
            5. 包含参数的内联函数是 | 5. 包含表达式的宏必须是 一次处理,然后可以多次使用|每次使用时都会处理。 时间。 |

            【讨论】:

              【解决方案8】:

              内联函数远比宏好。例如,如果内联函数大到足以减慢代码的执行速度,编译器不会使其内联,因为宏没有这样的检查

              【讨论】:

                猜你喜欢
                • 2020-03-13
                • 1970-01-01
                • 2014-09-19
                • 1970-01-01
                • 2013-10-21
                • 1970-01-01
                • 2010-09-14
                • 2019-09-10
                相关资源
                最近更新 更多