【问题标题】:Is it possible to only include a header once per project?是否可以每个项目只包含一次标题?
【发布时间】:2020-11-25 18:41:03
【问题描述】:

在更简单的语法之上,Go 声称它通过只导入一次依赖项在很大程度上实现了快速的编译速度:

Go 为所有文件导入一次依赖项,因此导入时间不会 随着项目规模呈指数增长。

如果你对你的设计很小心,是否有可能用 C++ 完成同样的事情?

说将所有包含添加到包含在所有文件中的单个包含文件(使用一次编译指示)?或者它会减慢很多,因为对任何标头的任何更改都会重新编译所有内容而不是增量?

我正在使用 LLVM。仍在构建项目。

【问题讨论】:

  • 有一种名为“unity”或“amalgamated”或“jumbo”或“单一编译单元”(SCU) 的项目技术,它将所有*.h*.cpp 文件包含在一个单一的超级中*.cpp 文件,然后编译它。我的一位同事在他的项目中将其作为一个实验,它使编译时间加快了 4 倍。然而,他们没有采用它,因为匿名命名空间和代码的布局方式会产生影响。对于 C++20,有一个名为 modules 的新功能(并且令人兴奋!),它甚至更好。

标签: c++ compilation dependencies header-files


【解决方案1】:

通常一个项目由许多 .cpp 文件组成。包含所有内容的 .cpp 文件是一个翻译单元 (TU)。它们分别编译,然后链接到可执行文件或 dll 中。

您的解决方案将强制每个 TU,尽管它的依赖项可能很小,但可能包含那个巨大的头文件。它将被包含一次,但对于项目中的每个 .cpp 文件一次。

很可能,它会使编译变慢。更不用说这种架构的所有问题了 - 保持这个代码库的健全会很痛苦。

您的问题中有一个见解 - 可能您想要的是预编译的标头。在某些情况下谨慎使用它们可以缩短编译时间。

【讨论】:

  • 并且可能会破坏增量构建。
【解决方案2】:

是的,通过仔细管理代码结构可以大大减少 C++ 中的构建时间。

实现这一目标的一种方法是广泛使用前向声明。 有一个工具可以帮助实现这一目标:Include What You Use

为了使这更有效,您还必须防止编译器在头文件中生成构造函数、析构函数和赋值运算符的默认实现。所以在 header 中声明它们,然后在各自的 cpp 中默认定义它们可以帮助在头文件中保持一些类向前声明。

加快构建时间的另一种方法是广泛使用依赖倒置。但这是任何语言的一般规则。


令人高兴的是,C++20 提供了模块支持,这应该会使这些事情变得更加容易(不再有头文件)。

【讨论】:

    【解决方案3】:

    许多编译器都支持“预编译头文件”。因此,即使给定的头文件在多个翻译单元中使用,编译器也只会在第一次编译它并缓存结果以供后续单元使用。检查您的编译器文档是否支持此功能以及如何使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-08
      • 2021-03-19
      • 2013-05-19
      • 2011-07-31
      • 1970-01-01
      • 1970-01-01
      • 2016-05-15
      • 2016-01-03
      相关资源
      最近更新 更多