理解问题:预编译 headers & include usage

Comprehension issue: Precompiled headers & include usage

我遇到了有关预编译 header 和 #include 指令用法的理解问题。 所以我在这里得到了我的 "stdafx.h" 并在那里包含了例如矢量、iostream 和字符串。关联的"stdafx.cpp"只包含"stdafx.h",很清楚。

因此,如果我设计自己的 header 文件,例如使用 vector 或 iostream 中的 "code",我必须包含 header 文件,因为编译器不知道当时的声明。那么为什么这里的一些帖子 (include stdafx.h in header or source file?) 说,将 "stdafx.h" 包含在其他 header 文件中是不好的,即使这个文件包含所需的声明,例如矢量?所以基本上直接包含向量或预编译的 header 文件都没有关系,两者做同样的事情。

我当然知道,如果关联的源文件包含所需的 header 文件,我不必将 header 文件包含在另一个 header 文件中,因为当时的声明是已知的。好吧,只有当 header 文件包含在某处时才有效。

所以我的问题是:我应该避免在任何源文件中包含预编译的 header 文件吗?为什么?我有点困惑,因为我在网上读到一些相互矛盾的说法,我不应该在 header 文件中包含任何内容,或者是 O.K。包含在 header 个文件中? 那么现在怎么样了?

使用预编译 header 功能时,每个 .cpp 文件必须以包含 stdafx.h header 开头。如果不是,则会导致编译器错误。所以将 include 放入某些 header 文件中是没有意义的。该 header 文件不能被包含,除非 stdafx.h 已经被首先包含。

预编译 headers 是一种缩短构建时间的方法。这个想法是编译器可以在 header 中 "precompile" 声明和定义,而不必再次解析它们。

以当今计算机的速度,预编译只对大型项目有意义。这些项目至少有超过 5 万行代码。 "signification" 的定义通常需要几十分钟才能构建。

Microsoft stdafx.h 存在许多问题。根据我的经验,发现和解决问题所花费的精力和时间,使得此功能对于较小的项目规模来说更麻烦。我已经设置了我的构建,所以大部分时间我只编译几个文件;不改变的文件不会被编译。因此,我看不到预编译的 header.

有任何巨大的影响或好处。

这将是一个有意图的笼统声明。 Visual Studio 项目 follows this general design 中 PCH 的典型设置,值得回顾。也就是说:

  1. 像没有 PCH master-header 一样设计你的 header 文件。
  2. 切勿在您的 header 中构建您希望包含的源文件将在您的 header 之前完成的 include-order 依赖项。
  3. 尽管有 PCH master-header(我稍后会讲到),但请务必在 headers before 标准 [=141] 之前包含您的自定义 headers =]s 在你的源文件中。这使得您的自定义 header 更有可能被正确定义,而不依赖于包含源文件之前包含的某些标准 header 文件。
  4. 始终设置适当的包含守卫或编译指示以避免多重包含。它们对于此功能的正常运行至关重要。

PCH master-header 不包含在您的 header 文件中。在设计您的 header 时,请考虑 header 进行编译。如果一个包含源文件需要额外的包含来实现它,它可以在你的 header 之后根据需要将它们拉进来。

以下是我如何设置在 .h 和 .cpp 文件中使用多个标准 header 的项目的示例。

myobject.h

#ifndef MYAPP_MYOBJECT_H
#define MYAPP_MYOBJECT_H

// we're using std::map and std::string here, so..
#include <map>
#include <string>

class MyObject
{
    // some code

private:
    std::map<std::string, unsigned int> mymap;
};

#endif

请注意上面的 header 应该在包含它的任何 .cpp 中编译,使用或不使用 PCH。关于源文件...

myobject.cpp

// apart from myobject.h, we also need some other standard stuff...

#include "myobject.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <numeric>

// code, etc...

注意 myobject.h 不希望您包含它所依赖的内容。它没有在 header 中使用 <iostream><algorithm> 等;我们在这里使用它。

这是没有 PCH 的典型设置。现在我们添加 PCH master


添加PCH主机Header

那么我们如何设置PCHmaster-header到turbo-charge这个东西呢?为了这个答案,我只处理引入标准 headers 和 3rd-party 库 headers,它们不会随着项目开发而改变。您不会编辑 <map><iostream>(如果是,请检查您的头部)。无论如何...

  1. See this answer 了解如何在 Visual Studio 中配置 PCH。它显示了一个文件(通常是 stdafx.cpp)如何负责生成 PCH,其余的源文件然后通过包含 stdafx.h.

    [=96= 使用 said-PCH ]
  2. 决定 PCH 中的内容。作为一般规则,这就是您的 PCH 应该如何配置。把 non-volatile 东西放在那里,剩下的留给常规源包含。我们正在使用许多系统 headers,这些将成为我们的 PCH 主机的选择。

  3. 确保参与 PCH turbo-mode 的每个源文件都包括 PCH master-header first,如链接答案中所述来自 (1).

所以,首先,PCH master header:

stdafx.h

#ifndef MYAPP_STDAFX_H
#define MYAPP_STDAFX_H

// MS has other stuff here. keep what is needed

#include <algorithm>
#include <numeric>
#include <iostream>
#include <fstream>
#include <map>
#include <string>

#endif

最后将源文件配置为使用这个然后再做这个。需要的 最小 更改是:

更新:myobject.cpp

#include "stdafx.h" // <=== only addition
#include "myobject.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <numeric>

// code, etc...

注意我说的是最小。实际上,这些标准 header 中的 none 需要再出现在 .cpp 中,因为 PCH 主机正在将它们拉入。换句话说,您 可以 这样做:

更新:myobject.cpp

#include "stdafx.h"
#include "myobject.h"

// code, etc...

选择与否由你决定。我更喜欢保留它们。是的,它 可以 延长源文件的预处理器阶段,因为它拉入 headers,运行到 include-guards,然后丢弃所有内容直到最后#endif。如果您的平台支持 #pragma once(而 VS 支持),那将成为接近 no-op.

但请不要误会:所有这一切中最重要的部分是 header myobject.h 根本没有改变 包含或知道 PCH 主机 header。它不应该,也不应该建造,所以它必须。