在Visual Studio中,“stdafx.h”用于什么?

564
当我在Visual Studio 2010中启动一个项目时,会自动生成名为stdafx.h的文件。由于我需要创建一个跨平台的C++库,因此不能使用该头文件。 stdafx.h用于什么?我只是删除这个头文件可以吗?

2
如果我遇到与stdafx.h相关的编译错误,通常会将设置更改为不创建或使用此文件。 - phoad
8
文章标题:新手必看的StdAfx.h - http://www.viva64.com/en/b/0265/本文将介绍什么是StdAfx.h文件,以及如何正确地使用它。StdAfx.h通常是Microsoft Visual Studio中项目的标准头文件,用于包含与预编译头相关的声明和定义。使用StdAfx.h可以显着加快编译速度,尤其是对于大型项目而言。然而,不正确地使用或者不完整地包含StdAfx.h可能会导致编译错误或链接错误。文章将提供一些实用的建议来避免这些问题,并展示如何在不同的情况下正确使用StdAfx.h文件。 - user965097
你可以在其他平台上很好地使用这个头文件,对它们来说只是一个普通的头文件。但在那里它并没有提供任何性能优势。 - Andrea
5个回答

922
所有的C++编译器都有一个严重的性能问题需要处理。编译C++代码是一个漫长而缓慢的过程。
编译包含在C++文件顶部的头文件是一个非常漫长而缓慢的过程。编译构成Windows API和其他大型API库的巨大头文件结构是一个非常、非常缓慢的过程。不得不为每个单独的Cpp源文件反复编译它,简直就是丧钟。
这并不是Windows特有的问题,而是所有必须编译大型API(如Windows)的编译器面临的老问题。
微软编译器可以通过一种称为“预编译头文件”的简单技巧来缓解这个问题。这个技巧非常聪明:虽然每个CPP文件都可能合法地对包含在每个Cpp文件顶部的头文件链条给出略微不同的含义(例如通过使用不同的宏#define提前包含或以不同的顺序包含头文件),但这在大多数情况下并不是真实情况。大部分时间,我们有几十个或几百个包含文件,但它们都被认为对于编译在应用程序中的所有Cpp文件具有相同的含义。
如果编译器不必从头开始编译每个CPP文件以及其数十个包含文件,它可以节省大量时间。
这个技巧的要点在于将一个特殊的头文件指定为所有编译链的起点,所谓的“预编译头”文件,出于历史原因通常是一个名为stdafx.h的文件。
只需在stdafx.h文件中以适当的顺序列出所有API的大型头文件,然后在每个CPP文件的顶部开始时使用#include“stdafx.h”,而不是有意义的内容(在此之前允许的几乎唯一的内容是注释)。
在这些条件下,编译器不是从零开始编译,而是从已经保存在stdafx.h中编译一切的结果开始编译。
我不认为这个技巧是微软编译器独有的,也不认为它是一项原创开发。对于 Microsoft 编译器,控制使用预编译头文件的设置由编译器的命令行参数控制:/Yu "stdafx.h"。可以想象,stdafx.h 文件名的使用只是一种约定;如果你愿意,可以更改名称。
在 Visual Studio 2010 中,通过右键单击 CPP 项目,选择“属性”,并导航到“配置属性\C/C++\预编译头”来控制此设置。对于其他版本的 Visual Studio,GUI 中的位置将有所不同。
请注意,如果禁用预编译头文件 (或通过不支持它们的工具运行项目),这并不会使你的程序非法;它只是意味着你的工具每次都会重新编译所有内容。
如果你正在创建一个没有 Windows 依赖项的库,可以轻松地注释掉或删除 #include 语句从 stdafx.h 文件中。没有必要删除该文件本身,但是通过禁用上面的预编译头设置也可以这样做。

8
即使你只使用std命名空间中的文件,也能获得速度优势。 - Ghita
13
确实是非常好的回答。我正在寻找符合标准的 C 编译器。结果发现,我可以从项目属性中禁用微软扩展,将编译器从“自动”更改为“c”,这样你就几乎拥有了“标准”的编译器和集成开发环境。 - EKanadily
4
@Rishi:你所说的“line”是指#include "stdafx.h"吗?没错,但那只是一个标准的#include语句。 “MS扩展”部分只是编译器性能优化的一部分;它并不改变包含名为“stdafx.h”的头文件的语义。请注意,如果你移除了这个include语句,而你的代码依赖于通过stdafx.h被包含的任何内容,你将需要直接include这些内容。 - Euro Micelli
4
@Youda008,不完全正确。在编译代码文件之前,头文件的内容仅仅被“粘贴”到源代码中包含它们的位置(由同一步骤中评估宏的“预处理器”完成)。产生的总文件然后被传递给实际的编译器,它从未将头文件视为单独的实体。你只是将声明放在头文件中,因为这对头文件来说效果很好 - 这是一条惯例。试试吧!创建一个包含整个程序的头文件,然后创建一个只有一个#include的源文件。它可以成功编译。 - Euro Micelli
40
历史的好奇心。stdafx.h 的名字可以追溯到约1992年,当时 MFC 在发布之前被称为“应用程序框架扩展”。即使在 Visual Studio 2015 中,默认名称仍然是……(原文未完整,无法翻译) - kert
显示剩余17条评论

55

这是一个“预编译头文件”——在stdafx.h中包含的任何头文件都会被预处理以节省后续编译的时间。你可以在MSDN上了解更多信息。

如果您正在构建跨平台应用程序,请在创建项目时选择“空项目”,Visual Studio则不会将任何文件添加到您的项目中。


19
这个文件在其他平台上都可以运行,如果编译器不支持预编译头文件可能会减慢编译速度,但不会导致编译失败。它只是一个包含其他头文件的头文件。 - detunized
2
@detunized:也许我的回答让人产生了误解,所以感谢你澄清了那一部分。 - casablanca

5
"Stdafx.h" 是预编译头文件。它包含标准系统包含文件和项目特定的包含文件,这些文件经常使用但不经常更改。这可以减少编译时间和不必要的处理。
预编译头文件 stdafx.h 在 Microsoft Visual Studio 中基本上用于让编译器知道哪些文件已经编译过,不需要从头开始重新编译。您可以阅读更多相关信息。

http://www.cplusplus.com/articles/1TUq5Di1/

https://learn.microsoft.com/en-us/cpp/ide/precompiled-header-files?view=vs-2017


3

定义: "Stdafx.h" 是一个预编译头文件。

  • 预编译的意思是一旦编译过,就不需要再次编译。
  • stdafx.h 主要用于 Microsoft Visual Studio 中,让编译器知道这些文件已经编译过了,无需从头开始编译。

例如: 如果您正在包含以下 Windows 头文件。

代码:

#include <windows.h>
#include <string.h>

int main()
{
 //your code
return 0;
}
  • 编译器总是从头开始编译这些头文件。
  • 但如果在这些头文件之前包含 #include "stdafx.h",则编译器将从 stdafx.h 中找到已编译的头文件,而不是从头开始编译。
  • 对于第一次编译,编译器会像平常一样从头开始编译。

代码:

#include "stdafx.h"
#include <windows.h>
#include <string.h>

int main()
{
//your code
 return 0;
}

优点:

  • 减少编译时间。
  • 减少不必要的处理。

来源:http://www.cplusplus.com/articles/1TUq5Di1/


-14

我自己也遇到了这个问题,因为我正在尝试创建一个基本的框架,但是一开始在Visual Studio 2017中创建了一个新的Win32程序选项。 "stdafx.h"是不必要的,应该被删除。然后,您可以从解决方案资源管理器中删除愚蠢的"stdafx.h"和"stdafx.cpp"以及项目中的文件。取而代之的是,您需要放置

#include <Windows.h>

instead.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接