【问题标题】:automatically inlined functions across translation units and gcc 4.6跨翻译单元和 gcc 4.6 的自动内联函数
【发布时间】:2012-03-19 09:05:46
【问题描述】:

如果我没有将函数 f 声明为内联。如下:

啊哈:

X f(Y y);

A.cpp:

X f(Y y)
{
    ...
}

然后在不同的翻译单元中:

B.cpp:

#include "A.h"

Z g(W w)
{
    ...
    ... f(...) ...
    ...
}

然后我用gcc 4.6编译两个翻译单元A.o和B.o,然后也通过gcc链接它们。 (可能在两个步骤中都使用 -O3)

gcc 会考虑在链接时内联函数以提高性能吗?还是为时已晚?

在一次代码审查中,有人建议我不应该将我的函数声明为内联,因为编译器比我何时内联更清楚。除非函数在头文件中定义,否则我总是印象深刻,编译器没有内联它的选项。

(如果 C 模式、C++ 模式或 gnu++0x 模式的答案不同,请同时指出)

【问题讨论】:

  • 为什么要做这样的事情? inline 就是为此而发明的。它允许您在头文件中定义函数,而不会出现“多个定义的符号”错误。现在它工作得很好,编译器有很好的策略来有效地内联函数。
  • @JensGustedt:为什么?懒惰。我宁愿优化器确定何时最好内联函数,就像它确定何时将局部变量放入寄存器而不是堆栈一样。我认为这是一个没有争议的观点,而你没有抓住重点。
  • 嗯,这正是我所说的。让编译器有机会为你做这件事。 inline 除了要求编译器在适当的时候执行之外,没有别的意思。为了与您的示例保持一致,局部变量在编译器决定将其保存在寄存器中或溢出时是完全可见的。编写干净的代码,编译器会对你很好。坦率地说,为什么在头文件中定义函数比在 .c 中更难?完全相同的文字出现在不同的地方?
  • @JensGustedt:所以现在你建议所有函数都应该在标题和inline 中定义?两个问题(1)修改实现会导致接口依赖(以及随之而来的连锁反应)重新编译,(2)inline 关键字会使每个函数签名变得混乱。
  • 我在哪里说“全部”? inline 不是签名的一部分,AFAIK。而你所要求的,链接时间“内联”会在代码之间引入比这更微妙的依赖关系。

标签: c++ c gcc


【解决方案1】:

该功能称为Link Time Optimization(LTO),在 GCC 4.6 中默认未启用

[编辑] 启用 LTO 后,GCC 将在 A.obj 中保存 X f(Y y) 的“GIMPLE”表示。这种表示比通常的 C++ 预处理稍微多一些,但不是很多。特别是,它还没有被翻译成汇编。结果,链接器仍然可以内联它。

【讨论】:

  • 您能否添加一个简短的描述,说明它在这个特定场景中是如何工作的?我对此一无所知。
【解决方案2】:

我不认为 gcc 可以创建将 make 函数拆分为内联的不同源文件。只有在同一个源文件中声明它们才有效。

【讨论】:

    【解决方案3】:

    编译器可以选择内联或不内联以提高性能。但在这种情况下,我认为编译器是无助的。它不可能内联函数 f。

    注意:即使您使用关键字,它也只是一个建议。是否内联的最终决定取决于编译器。所以建议编译器没有任何问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-09
      • 1970-01-01
      • 2019-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多