zoukankan      html  css  js  c++  java
  • 关于预编译和Stdafx.h的若干问题

    预编译

    预编译头的概念:

    所谓的预编译头就是把一个工程中的那一部分代码,预先编译好放在一个文件里(通常是以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C++代码--------甚至是inline的函数,但是必须是稳定的,在工程开发的过程中不会被经常改变。如果这些代码被修改,则需要重新编译生成预编译头文件。注意生成预编译头文件是很耗时间的。同时你得注意预编译头文件通常很大,通常有6-7M大。注意及时清理那些没有用的预编译头文件。

    也许你会问:现在的编译器都有Time stamp的功能,编译器在编译整个工程的时候,它只会编译那些经过修改的文件,而不会去编译那些从上次编译过,到现在没有被修改过的文件。那么为什么还要预编译头文件呢?答案在这里,我们知道编译器是以文件为单位编译的,一个文件经过修改后,会重新编译整个文件,当然在这个文件里包含的所有头文件中的东西(.eg Macro, Preprocesser )都要重新处理一遍。VC的预编译头文件保存的正是这部分信息。以避免每次都要重新处理这些头文件。

    预编译头的作用:

    方法一:手动方法

    根据上文介绍,预编译头文件的作用当然就是提高编译速度了,有了它你没有必要每次都编译那些不需要经常改变的代码。编译性能当然就提高了。

    预编译头的使用:

    要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件)

    想必大家都知道 StdAfx.h这个文件。很多人都认为这是VC提供的一个“系统级别”的,编译器带的一个头文件。其实不是的,这个文件可以是任何名字的。我们来考察一个典型的由AppWizard生成的MFC Dialog Based 程序的预编译头文件。(因为AppWizard会为我们指定好如何使用预编译头文件,默认的是StdAfx.h,这是VC起的名字)。我们会发现这个头文件里包含了以下的头文件:

    #include <afxwin.h>     // MFC core and standard components

    #include <afxext.h>     // MFC extensions

    #include <afxdisp.h>   // MFC Automation classes

    #include <afxdtctl.h>       // MFC support for Internet Explorer 4 Common Controls

    #include <afxcmn.h>  

    这些正是使用MFC的必须包含的头文件,当然我们不太可能在我们的工程中修改这些头文件的,所以说他们是稳定的。

    那么我们如何指定它来生成预编译头文件。我们知道一个头文件是不能编译的。所以我们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件里只有一句代码就是:#include “Stdafx.h”。原因是理所当然的,我们仅仅是要它能够编译而已―――也就是说,要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指定StdAfx.cpp来生成一个.pch文件,通过/Fp编译开关来指定生成的pch文件的名字。打开project ->Setting->C/C++ 对话框。把Category指向Precompiled Header。

    在图中我们的Project Options(右下角的那个白的地方)可以看到 /Fp “debug/PCH.pch”,这就是指定生成的.pch文件的名字,默认的通常是 <工程名>.pch(我的示例工程名就是PCH)。

    这时原来的Project Option变成了 Source File Option(原来是工程,现在是一个文件,当然变了)。在这里我们可以看到 /Yc开关,/Yc的作用就是指定这个文件来创建一个Pch文件。/Yc后面的文件名是那个包含了稳定代码的头文件,一个工程里只能有一个文件的可以有YC开关。VC就根据这个选项把 StdAfx.cpp编译成一个Obj文件和一个PCH文件。


    在这里,Precomplier 选择了 Use ………一项,头文件是我们指定创建PCH 文件的stdafx.h

    文件。事实上,这里是使用工程里的设置,/Yu”stdafx.h”。

    这样,我们就设置好了预编译头文件。也就是说,我们可以使用预编译头功能了。以下是注意事项:

    1):如果使用了/Yu,就是说使用了预编译,我们在每个.cpp文件的最开头,我强调一遍是最开头,包含 你指定产生pch文件的.h文件(默认是stdafx.h)不然就会有问题。如果你没有包含这个文件,就告诉你Unexpected file end. 如果你不是在最开头包含的,你自己试以下就知道了,绝对有很惊人的效果…..

    2)如果你把pch文件不小心丢了,根据以上的分析,你只要让编译器生成一个pch文件就可以了。也就是说把 stdafx.cpp(即指定/Yc的那个cpp文件)从新编译一遍就可以了。当然你可以傻傻的 Rebuild all。简单一点就是选择那个cpp文件,按一下Ctrl + F7就可以了。

    方法二。自动使用

    很简单只要指定/YX就可以了。或者在上图中选择Automatic………就可以了。注意的事情是如果你指定了/Yc /Yu的话,/Yx是会被忽略的。前者的优先级别高一些。

    一、什么是预编译头?
    预编译头物理上与通常的的.obj文件是一样的,但编译入预编译头的.h,.c,.cpp文件在整个编译过程中,只编译一次,如预编译头所涉及的部分不发生改变的话,在随后的编译过程中此部分不重新进行编译。进而大大提高编译速度,并便于对头文件进行管理,也有助于杜绝重复包含问题。

    二、什么时候使用预编译头?
    当大多.c或.cpp文件都需要相同的头文件时。
    当某些代码被大量重复使用时。
    当导入某些不同库都有实现的函数,并产生混乱时。

    stdafx.h

     
     

    编辑本段简介

      名称的英文全称为:Standard Application Framework Extensions
     
      所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。
     
      预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。
     
      编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include "stdafx.h"前的代码都是预编译的,它跳过#include "stdafx. h"指令,使用projectname.pch编译这条指令之后的所有代码。
     
      afx曾经是微软一个专门的技术开发团队,而stdafx.h则是这个团队为了定义一些环境配置、参数设置等专门定义的。
     
     

    编辑本段工作原理及作用

      stdafx.h中没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行。
     
      Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程序也要花费相当长的时间来完成工作。由于每个.CPP文件都包含相同的include文件,为每个.CPP文件都重复处理这些文件就显得很傻了。
     
      为避免这种浪费,AppWizard和VisualC++编译程序一起进行工作,如下所示:
     
      ◎AppWizard建立了文件stdafx.h,该文件包含了所有当前工程文件需要的MFCinclude文件。且这一文件可以随被选择的选项而变化。
     
      ◎AppWizard然后就建立stdafx.cpp。这个文件通常都是一样的。
     
      ◎然后AppWizard就建立起工程文件,这样第一个被编译的文件就是stdafx.cpp。
     
      ◎当VisualC++编译stdafx.cpp文件时,它将结果保存在一个名为stdafx.pch的文件里。(扩展名pch表示预编译头文件。)
     
      ◎当VisualC++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。VisualC++不再分析Windowsinclude文件,除非你又编辑了stdafx.cpp或stdafx.h。
     
      这个技术很精巧,你不这么认为吗?(还要说一句,Microsoft并非是首先采用这种技术的公司,Borland才是。)在这个过程中你必须遵守以下规则:
     
      ◎你编写的任何.cpp文件都必须首先包含stdafx.h。
     
      ◎如果你有工程文件里的大多数.cpp文件需要.h文件,顺便将它们加在stdafx.h(后部)上,然后预编译stdafx.cpp。
     
      ◎由于.pch文件具有大量的符号信息,它是你的工程文件里最大的文件。
     
      如果你的磁盘空间有限,你就希望能将这个你从没使用过的工程文件中的.pch文件删除。执行程序时并不需要它们,且随着工程文件的重新建立,它们也自动地重新建立。
     

    编辑本段stdafx.h的作用

      当我们使用AppWizard来自动生成某些项目的时候,系统会自动把所需要include的头文件在stdafx.h中先include一下,这样,我们只需要直接include这个stdafx.h文件即可.因为同一个项目中的不同源文件CPP都包含相同的include文件,这样,为每个.CPP文件都重复include这些文件就显得很傻了。
     
      具体在stdafx.h中需要include什么头文件,取决于用户在AppWizard中的选择.
     
      比如:
     
      #include <afxwin.h> // MFC core and standard components
     
      #include <afxext.h> // MFC extensions
     
      #include <afxole.h> // MFC OLE classes
     
      #include <afxodlgs.h> // MFC OLE dialog classes
     
      #include <afxdisp.h> // MFC Automation classes
     
      ......
     
      等等,这样,就方便多了.所以,stdafx.h是自动生成的.这就使得用户在开发中不必在每一个cpp文件中都烦琐的include头文件了,而且,维护起来也方便.
     
      在生成stdafx.h头文件的同时,也生成了stdafx.cpp源文件,该源文件只包含#include "stdafx.h"语句,这是在编译过程中第一个被编译的文件,编译的结果保存在一个名为stdafx.pch的文件里。 (扩展名pch表示预编译头文件。)当Visual C++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。 Visual C++不再分析Windows include文件,除非用户又编缉了stdafx.cpp或stdafx.h。
     
      看了这样的讲解,我马上就实验了一下,自己新建立一个windows窗口项目,很快,就生成了stdafx.cpp和stdafx.h.
     
      并且,在主源文件form1.cpp中,就include此头文件stdafx.h.
     
      以上情况,只在使用AppWizard来自动生成项目的时候,才出现.否则,就没有必要include此头文件stdafx.h了
     

    编辑本段其他

      stdafx.h : 标准系统包含文件的包含文件。
     
      Microsoft C 和 C++ 编译器提供了用于预编译任何 C 或 C++ 代码(包括内联代码)的选项。利用此性能特性,可以编译稳定的代码体,将已编译状态的代码存储在文件中,以及在随后的编译中,将预编译的代码与仍在开发的代码结合起来。由于不需要重新编译稳定代码,因此后面每次编译的速度都要快一些。
     
      预编译代码有助于在开发周期中缩短编译时间,特别是在以下情况中:
     
      一:总是使用不经常改动的大型代码体。
     
      二:程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个预编译头。
     
      三: 用于创建预编译头文件的第一次编译所花费的时间比后面的编译稍长一些。通过包含预编译代码可以加快后面的编译速度。C 和 C++ 程序都可以预编译。在 C++ 编程中,常见的做法是将类接口信息分别放到不同的头文件中。此后就可以将这些头文件包含在使用该类的程序中。通过预编译这些头文件,可以缩短程序的编译时间。
     
      VC创建项目时自动创建的预编译头文件,在编译其他文件之前,VC先预编译此文件。头文件stdafx.h引入了项目中需要的一些通用的头文件,比如window.h等,在自己的头文件中包括stdafx.h就包含了那些通用的头文件。
     
      所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。
     
      预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。
     
      编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include "stdafx.h"前的代码都是预编译的,它跳过#include "stdafx. h"指令,使用projectname.pch编译这条指令之后的所有代码。
     
      因此,所有的CPP实现文件第一条语句都是:#include "stdafx.h"。
     
     

    个人理解:

    因为.h文件不能单独编译,所以专门用一个StdAfx.cpp文件(仅包含一句#include"StdAfx.h")来生成预编译文件"项目名.pch"放在项目文件中以避免重复的编译工作。
    "项目名.pch"存放在项目的Debug文件夹中,里面存放的是二进制码
    Stdafx.h文件必须得包含在"项目名.cpp"文件中否则无法通过编译
  • 相关阅读:
    bzoj 4911: [Sdoi2017]切树游戏
    bzoj 2654: tree
    bzoj 3240: [Noi2013]矩阵游戏
    有标号的DAG计数 III
    有标号的DAG计数 II
    bzoj 3512: DZY Loves Math IV
    bzoj 4480: [Jsoi2013]快乐的jyy
    bzoj 5323: [Jxoi2018]游戏
    codeforces412A
    7.6 T1 深度优先搜索(dfs)
  • 原文地址:https://www.cnblogs.com/langzi93/p/2423773.html
Copyright © 2011-2022 走看看