为啥对于 VisualStudio 来说包含 stdafx.h 还不够?

Posted

技术标签:

【中文标题】为啥对于 VisualStudio 来说包含 stdafx.h 还不够?【英文标题】:Why isn't include stdafx.h not enough for VisualStudio?为什么对于 VisualStudio 来说包含 stdafx.h 还不够? 【发布时间】:2017-02-10 20:03:20 【问题描述】:

我了解预编译头文件的目的是通过使用已经编译过一次的目标文件并将其链接到实际项目来加快编译过程。但我不明白的是,为什么我要明确强制 Visual Studio 使用stdafx.h(项目属性 -> C/C++ -> 预编译头文件 -> 预编译头文件)?为什么#include "stdafx.h" 还不够?

【问题讨论】:

你必须告诉 IDE 是否创建 PCH。 请不要盲目投反对票,请提供提示有问题应该改进的地方。谢谢 【参考方案1】:

为什么#include "stdafx.h" [...] 还不够?

因为这只是一个标准的 C++ 预处理器指令。* 就编译器而言,它与 #include <string> 没有什么不同。如果你需要附加额外的语义,你必须告诉编译器。

由于似乎存在混淆,Visual Studio 如何实现预编译的标头,这里是文档的链接:Creating Precompiled Header Files。


*请注意,"stdafx.h" 这个名称没有什么特别之处,只是它是用于生成 PCH 的默认标头名称。

【讨论】:

在我的 Visual Studio 项目中同意 PCH 标头甚至没有命名为 stdafx.h。尽管我在 CMake 中使用了一个宏来指定 PCH 标头的名称.. 对不起,我不关注。什么额外的语义?编译器只是将#include "stdafx.h" 替换为stdafx.h 的内容。从这一点开始,我可以调用stdafx.h 中声明的函数,编译器不会抱怨。编译后stdafx.obj 文件与我的项目链接。我认为没有必要在这里明确指定其他内容。 @WakanTanka:您已经描述了标准语义。附加的语义是,编译器用 pre-processedpre-compiled 版本的标头替换 #include 指令。此外,头文件不是编译单元。没有 "stdafx.obj" 文件(除非您还提供了一个 "stdafx.cpp" 文件,您可以为 PCH 提供该文件)。不过,.obj 文件与 PCH 无关。 没有什么不允许编译器使用预编译头来实现#include "stdafx.h",只要它的行为与标准 C++ 预处理器指令相同,并且可以像往常一样回退到包含文件。不,这不仅仅是理论上的,至少 GCC 确实如此。 @IInspectable 您的回答表明,#include 是标准 C++ 预处理器指令这一事实意味着它不会导致使用预编译的标头。一个真实世界编译器的反例,它完全表明该逻辑是不正确的。【参考方案2】:

所谓的stdafx.h应该看起来像一个普通的头文件。它的名字没有什么特别之处。它不应该自动启用预编译头。

这个想法是stdafx.h 将被任何其他编译器视为普通头文件和/或当您不使用 MSVC 中的预编译头文件时。

应该告诉 MSVC 编译器你实际上想要启用预编译头文件。这正是您拥有该项目设置的原因。并且只有当您启用预编译头文件时,stdafx.h 才会获得它的特殊角色,并会从编译器中得到特殊处理。而且不一定是stdafx.h。您可以通过在项目设置中指定不同的名称来将此特殊角色分配给任何其他标头。

事实上,在与 Microsoft 特定库或框架无关的项目中看到对 AFX 的引用将是一件很奇怪的事情。

【讨论】:

您能否更具体地说明从编译器收到stdafx.h 的具体特殊处理?它与经典的编译链接过程有何不同? @Wakan Tanka:标头预编译与“链接”无关。这是一个完全不同的过程。 stdafx.h收到的“特殊待遇”基本上是:它的内容只被预编译一次,然后以预编译的形式使用。仅此而已。 "您应该告诉 MSVC 编译器您实际上想要启用预编译头文件。"我做#include "stdafx.h"的时候不是告诉MSVC了吗? @WakanTanka:不。这与写 #include "myheader.h" 没有什么不同。只是一个头文件,没有特殊含义。 是的,我做到了。我真的很感激你试图提供帮助,但我仍然没有遵循。我知道#include "stdafx.h" 没有特殊含义,但我不明白为什么应该这样做。如果stdafx.obj 存在,为什么它不能在链接时使用。我不明白为什么stdafx.h 应该受到与任何常规头文件不同的威胁。有stdafx.h 然后有stdafx.cpp 包含它并在编译后从它创建stdafx.obj 并且这个stdafx.obj 在链接期间被链接。因此stdafx.obj 只创建一次,但每次我重新编译我的项目时都会链接。

以上是关于为啥对于 VisualStudio 来说包含 stdafx.h 还不够?的主要内容,如果未能解决你的问题,请参考以下文章

visualstudio2019如何运行c语言

为啥我的基于 postgis ST_Intersects 和 ST_Azimuth 的查询很慢?

为啥我的图像对于 iPhone 来说太大了

为啥刷新 Maven 存储库对于 IntelliJ 来说还不够?

为啥刷新令牌对于 SPA 来说被认为是不安全的?

为啥这个值对于我的 H2 表来说太长了