【问题标题】:c++ inline function?C++内联函数?
【发布时间】:2011-08-23 17:24:21
【问题描述】:

我为什么要这样做:

inline double square (double x) { return x*x;}

而不是

double square (double x) { return x*x;}

有区别吗?

【问题讨论】:

标签: c++ inline


【解决方案1】:

前者(使用inline)允许您将该函数放在一个头文件中,它可以包含在多个源文件中。使用inline 使标识符在文件范围 中,很像声明它static。如果不使用inline,您会从链接器中得到一个多符号定义错误。

当然,这是对编译器的提示,即应该将函数内联编译到使用它的位置(避免函数调用开销)。编译器不需要对inline 提示进行操作。

【讨论】:

  • 我认为内联的目的是让编译器'扩展'调用它的函数的内容,所以不会有vtable查找(或指令跳转到CPU上的函数级别)。
  • 你的第一点是预期目的的[有用]副作用吗?
  • @Ian Fleeton:确实是副作用;如果内联标识符没有文件范围,那么根本不可能将内联函数定义放在头文件中。
  • @Greg:它不像static。如果是这样,每个翻译单元将对它的函数副本拥有自己的所有权,并且链接器会将它们全部视为不同的函数(恰好具有相同的名称)。相反,inline 指示链接器,如果它看到此函数的不同定义,它们都是相同的,必须合并为一个。但是忽略这个细节,它在大多数情况下确实表现得好像是static
  • @DJ:inline 无法阻止 vtable 查找,您需要为此调用去虚拟化
【解决方案2】:

在现代编译器上可能没有太大区别。它可能在没有inline 的情况下被内联,它可能被内联 inline

【讨论】:

  • 有道理,我从参考和 10 年的经验出发。
【解决方案3】:

是的,有区别。 https://isocpp.org/wiki/faq/inline-functions.

当您指定一个函数是内联的时,您会导致编译器将该方法的代码放在任何被调用的地方。

void myfunc() {
  square(2);
}

等同于

void myfunc() {
   2 * 2;
}

调用函数有利于代码清晰,但是当调用该函数时,必须将本地状态推入堆栈,为该方法设置一个新的本地状态,完成后需要返回之前的状态弹出。这是很多开销。

现在,如果您提高优化级别,编译器将做出诸如展开循环或内联函数之类的决定。编译器仍然可以随意忽略内联语句。

【讨论】:

  • 我认为使用 gcc 您可以使用编译标志 -Winline 在函数不会被内联时发出警告。如果您是一名受虐狂,您可以将其与 -Werror 结合使用。
  • "编译器仍然可以忽略内联语句。"事实上,每个现代编译器都这样做。
【解决方案4】:

来自 Wikipedia:内联函数是要求编译器执行内联扩展的函数。换句话说,程序员要求编译器在每个调用函数的地方插入完整的函数体,而不是在定义的地方生成代码来调用函数。编译器没有义务尊重这一要求。

http://en.wikipedia.org/wiki/Inline_function

【讨论】:

    【解决方案5】:

    inline过程抽象的概念配合得很好

    inline double square (double x) { return x*x;}
    
    int squareTwice(double x) {
        double first = square(x);
        double second = square(x);
        return first * second; 
    }
    

    上面与下面基本相似:

    int squareTwice(double x) {
        double first = x*x;
        double second = x*x;
        return first * second; 
    }
    

    这是因为当编译器内联扩展函数调用时,函数的代码被插入到调用者的代码流中;因此,在程序上将第二个示例抽象为第一个示例可能更容易。

    过程抽象可以将例程分解为更易于阅读的较小子例程(尽管这可以是一种风格选择)。

    【讨论】:

      【解决方案6】:

      如果编译器符合要求,内联函数将在调用它的代码中包含内联函数,就好像没有调用任何函数一样(就好像您已将逻辑放在调用函数中一样)并避免函数调用开销.

      【讨论】:

      • 编译器如果不想内联函数也不必内联,即使指定了 inline 关键字。
      • @Alex Marlon 没有说编译器不会内联函数,只是说它不必。这些是非常不同的事情。
      猜你喜欢
      • 2017-01-05
      • 1970-01-01
      • 2014-12-24
      • 1970-01-01
      • 2023-03-10
      • 2011-03-07
      • 2010-11-06
      • 2014-11-05
      相关资源
      最近更新 更多