包含每个 header 是否会对性能产生影响?

Are there any performance implications to including every header?

假设我想使用 hex() 函数。我知道它在 <ios> header 中定义,我也知道它包含在 <iostream> header 中。不同之处在于 <iostream> 中有更多的功能和其他我不需要的东西。

从性能 stand-point 来看,我是否应该关心 including/defining 较少的功能,类 等而不是更多?

  • 运行 时间性能没有受到影响。
  • 但是,如果包含大量不必要的 header,编译时间可能会过长。
  • 此外,完成此操作后,您可以创建不必要的重新编译,例如,如果 header 已更改但不使用它的文件包含它。

在小型项目中(包括小型 header),这无关紧要。随着项目的发展,它可能。

如果标准说它在 header <ios> 中定义,那么包括 header <ios> 因为你不能保证它会被包括 in/through任何其他 header.

包含不必要的 headers 有以下缺点。

  1. 更长的编译时间,链接器必须删除所有未使用的符号。
  2. 如果您在 CPP 中添加了额外的 header,它只会影响您的代码。
  3. 但是,如果您将代码作为库分发,并且在 header 文件中添加了不必要的 header。客户端代码将承担定位您使用的 header 的负担。
  4. 不要相信间接包含,使用实际定义所需函数的 header。
  5. 作为良好的编程习惯,在项目中也应包含 headers,以减少依赖性。
//local header -- most dependent on other headers
#include <project/impl.hpp>
//Third party library headers -- moderately dependent on other headers
#include <boost/optional.hpp>
//standard C++ header -- least dependent on other header
#include <string>

不受影响的是 run-time,链接器将在编译期间删除未使用的符号。

TL;DR:一般来说,最好只包含您需要的内容。包含更多 可以 对二进制大小和启动产生不利影响(应该是微不足道的),但主要是 compilation-time 没有预编译 headers.


当然,您必须至少包括那些 header,保证涵盖您的所有用途。
无论如何,有时 "work" 可能会发生这种情况,因为标准 C++ header 都允许按照实现者的意愿相互包含,并且 header 允许在std-命名空间(参见 Why is "using namespace std" considered bad practice?)。

接下来,有时包含额外的 header 可能会导致创建额外的 objects(请参阅 std::ios_base::Init),尽管 well-designed 库会最大限度地减少此类(即据我所知,标准库中的唯一实例)。

但最大的问题实际上不是编译(和优化)二进制文件的大小和效率(应该不受影响,除了前一点,其影响应该微乎其微),但 compilation-time 而积极发展(另见 How does #include <bits/stdc++.h> work in C++?)。
后者(严重到委员会正在研究 modules-proposal,参见 C++ Modules - why were they removed from C++0x? Will they be back later on?)因添加多余的 header 而受到不利影响。

除非,当然,你正在使用 precompiled-headers(参见 Why use Precompiled Headers (C/C++)?),在这种情况下,在预编译的 headers 中包含更多内容,因此到处都是,而不是仅在需要的地方,因为只要那些 header 不被修改,大多数时候实际上会减少 compile-times。

有一个 clang-based 工具可以找出最小 headers,叫做 include-what-you-use
它分析了 clang AST 来决定,这既是优点也是缺点:
您不需要教它关于 header 提供的所有可用符号,但它也不知道在该修订版中事情是否以这种方式解决,或者它们是否符合合同。
所以你需要double-check它的结果。

包括不需要的 header 文件具有 一些 价值。

  1. 包含通常需要的 include 的剪切和粘贴确实需要更少的编码工作。当然,后来的编码现在因为不知道真正需要什么而受到阻碍。

  2. 尤其是在 C 中,其名称有限的 space 控件,包括不需要的 headers 会及时检测到冲突。假设代码定义了一个全局非 static 变量或函数恰好符合标准,例如 erfc() 来进行一些文本处理。通过包含 <math.h>,可以检测到与 double erfc(double x) 的碰撞,即使此 .c 文件不进行 FP 数学计算,但其他 .c 文件会进行计算。

    #include <math.h>
    char *erfc(char *a, char *b);
    

OTOH,如果 .c 文件不包含 <math.h>,在 link 时,将检测到碰撞。如果多年来代码库不需要 FP 数学而现在需要,只是检测在许多地方使用的 char *erfc(char *a, char *b),那么这种延迟通知的影响可能会很大。

IMO:尽合理的努力不包括不需要的 header 文件,但不要担心包括一些额外的文件,尤其是如果它们是常见的。如果存在自动化方法,请使用它来控制 header 文件包含。