标头实现和优化的内联关键字

Posted

技术标签:

【中文标题】标头实现和优化的内联关键字【英文标题】:Header Implementations And The inline keyword for Optimization 【发布时间】:2013-11-21 19:40:51 【问题描述】:

我正在处理一个项目,其中头文件中有大量代码。如果我使用的是 Visual Studio,这不是问题,因为它具有预编译的头文件等,但这是 Linux GCC 代码。

无论如何,它开始成为编译时间的一个问题。当然,模板必须保留在头文件等中,但大部分代码可以提取到实现文件中并作为静态库链接。所有的项目都使用这些头文件并且每次都被编译,所以创建一个静态库是有意义的。

头文件中的实现是内联的,或者这只是一个提示,就像 inline 关键字一样?这段代码对时间非常关键,我担心将实现移出标题。如果我使用 inline 关键字而不是在头文件中实现,我能达到同样的效果吗?

** 更新 ** 我知道 inline 只是对编译器的提示。我无法控制项目中的所有内容,我只想将所有内容从标题中移到库中而不影响性能。这真的会是一个尝试并看到的东西吗?我只想保持性能完全相同,但增加编译时间。

【问题讨论】:

您可以将预编译的头文件与 gcc 一起使用,例如***.com/questions/58841/precompiled-headers-with-gcc 如果将实现移出标头,则不能(通常)将其声明为内联。必须在每个使用它们的翻译单元中定义内联函数。 您尝试过统一构建吗? buffered.io/posts/the-magic-of-unity-builds 显式模板实例化也可能有所帮助。您还可以尝试在实现内联函数时拆分头文件,并在其定义中拆分一个单独的头文件。 【参考方案1】:

inline 关键字只是对编译器的提示,它可能希望内联该函数。它真正的目的是让你合法地“违反”单一定义规则。

为了内联一个函数,它的主体必须在调用点可见,这通常意味着如果你将函数移动到一个实现文件,它可能不再被内联。

但请记住,标题中最有可能的大型函数无论如何都不会被内联。还要考虑到在许多情况下,由于各种特定于架构的问题,内联函数实际上可能比调用的函数慢

【讨论】:

【参考方案2】:

inline 是优化提示,但也用于解决 ODR。

考虑改用整个程序优化/链接时优化。它允许您在多个文件中实现,基本上所有内容都有相同的机会进行优化(和内联),就好像它在同一个翻译单元中一样。

您的编译时间变得更快,但链接时间通常会受到影响,有时甚至会相当长。不过,您不需要为调试构建启用它,因此它可以立即显着缩短开发时间。

【讨论】:

【参考方案3】:

如果我使用的是 Visual Studio,这不是问题,因为它具有预编译的标头等

GCC 也有。

http://gcc.gnu.org/onlinedocs/gcc/Precompiled-Headers.html

【讨论】:

【参考方案4】:

inline 关键字并不意味着函数必须在定义函数的“行中”实现。如您所知,这是对编译器的提示,让它尝试编译,就好像函数中的几行在您调用它的地方一样。从而避免了保存地址以跳回、vtable 查找等的开销。

认为它在标题中调用更快,是一厢情愿的想法(编写代码的原始人)。

试一试,并在一个最小示例中将实现移动到 cpp 文件 - 主要一个对象一个内联函数一个调用它。一次在头文件中实现,一次在 cpp 文件中实现。然后看组装。没有区别。

【讨论】:

内联通常是不可能的,因为有 vtable 条目。

以上是关于标头实现和优化的内联关键字的主要内容,如果未能解决你的问题,请参考以下文章

inline 关键字对类成员模板函数的影响?

Go语言中的内联函数

CSS性能优化的技巧

c++ 中的 final 关键字是不是允许额外的编译器优化?

C++关键字 inline

内联函数