【问题标题】:Function method definition in .cpp vs .h.cpp 与 .h 中的函数方法定义
【发布时间】:2015-09-15 05:31:49
【问题描述】:

为了减少一个相当大的框架在工作中的编译时间,我正在考虑将 .h 文件中的类方法定义移动到它们关联的 .cpp 文件中,如果它们非常大或需要编译包含可以移动到关联的 .cpp 文件。为了清楚起见,下面是一个人为的例子(虽然Foo::inc 是一个小方法)

ma​​in.cpp

#include "Foo.h"

int main(int argc, char** argv) {
    Foo foo(argc);
    foo.inc();
    return foo.m_argc;
}

Foo.h 之前(还不需要 Foo.cpp)

class Foo {
public:
    int m_argc;
    Foo (int argc) : m_argc(argc) {}
    void inc() { m_argc++; }
};

Foo.h 之后

class Foo {
public:
    int m_argc;
    Foo (int argc) : m_argc(argc) {}
    void inc();
};

Foo.cpp

#include "Foo.h"

void Foo::inc() { m_argc++; }

很久以前,一位同事提到,在某些情况下,这可能会导致运行时性能下降。我在谷歌上寻找这个案例,但似乎找不到,这个问题的公认答案是我能找到的最接近的答案,但它没有给出案例,只是提到它可能发生:Moving inline methods from a header file to a .cpp files

附带说明,我对方法明确使用inline 的情况不感兴趣,我上面链接的答案只是我能找到的最接近我正在寻找的答案

什么情况(如果有)会导致运行时间变慢?

【问题讨论】:

  • 您的示例可能会放缓。在当前代码中,inc 函数被定义为内联非虚函数,因此编译器可以内联函数而没有函数调用开销。新版本需要完整的函数调用。如果大量使用 inc 函数,则内联函数可以节省大量资金。如果很少使用,则开销无关紧要。
  • @JonathanLeffler,谢谢,没有意识到这已经是我正在寻找的情况。我意识到在原始实现中内联是由编译器决定的,但是有没有办法在移动的版本中保留编译器的决定?
  • (只是把这些信息放在这里,我是在阅读 cmets 后发现的)据我所知,我需要 -flto 来优化跨模块链接时间。没有它,第二种情况将涉及函数调用,因此会更慢。但是-flto 有一些副作用(它可以增加文件的大小)
  • 只是想添加两个很好的参考:Can the linker inline functions? 和关于Benefits of inline functions in C++? 的更一般性的讨论。

标签: c++


【解决方案1】:

您的原始方法 void inc() { m_argc++; } 自动为 inline,因此允许编译器将调用替换为内联版本。

只要将方法从类定义中移出到模块中,这个方法就不再是inline,内联扩展不会发生,标准方法调用在那里,结果可能会更慢。

【讨论】:

  • 为什么不会内联??编译器无法检测到该方法是如此微不足道,如果它在不同的文件中应该被内联??
  • 模块是独立编译的。为了内联函数/方法,它的源代码必须可用,因此通常它必须存在于标头中。
  • 如果您使用的是 1995 年的编译器或为某些晦涩的嵌入式环境设计的编译器,这可能是正确的,但所有主要编译器现在都支持某种形式的链接时代码生成和优化,并且能够内联其他翻译单元中定义的函数。
  • 在阅读了一下之后,似乎我必须使用-flto 进行跨模块链接时间优化,所以我认为 dlask 的答案是正确的。 -flto 有我不喜欢的副作用所以我猜答案是肯定的,第二种情况更慢
  • 这个答案是完全错误的。任何相当现代(
【解决方案2】:

减少头文件依赖总是一个减少编译时间的好主意。它是 What techniques can be used to speed up C++ compilation times? 等列表中的顶级项目之一

我建议 - 如果还没有完成的话 - 看看使用 Profiling the C++ compilation process 占用你编译时间的主要玩家

还有一些帮助器可以对你的包含依赖项进行排序,请参阅Automate #include refactoring in C++

关于将代码移动到源文件是否会降低运行时性能的问题:这取决于。一般来说,如果你在头文件中有函数,你可以说你给了编译器一个内联的机会。

我喜欢引用C++ FAQ - Inlining

内联函数能提高性能吗?

是和不是。有时。也许吧。

没有简单的答案。内联函数可能会使代码 更快,他们可能会使其变慢。他们可能使可执行文件 更大,他们可能会使其更小。他们可能会导致颠簸,他们 可能会防止颠簸。他们可能是,而且经常是,完全 与速度无关。

编译器 - 可能稍后是链接器 - 用它做什么取决于您使用的编译器工具链以及您提供的 compiler/linker 选项。

参见例如inline - Using the GNU Compiler Collection

... GCC 在不优化时不会内联任何函数...

一些参考资料:

【讨论】:

  • 基本上这些都与问题无关,您可以根据放在顶部的 LTO 链接做出答案
  • @asimes 你是对的。我被“我的同事说它会降低运行时性能”分心。我缩小了答案的范围并添加了一些关于减少 C++ 编译时间的内容,因为我认为您可以节省在 .cpp 文件中移动代码的工作量。
猜你喜欢
  • 1970-01-01
  • 2012-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多