定義
名稱的英文全稱為:Standard Application Framework Extensions
所謂頭檔案預編譯,就是把一個工程(Project)中使用的一些MFC標準頭檔案(如Windows.H、Afxwin.H)預先編譯,以後該工程編譯時,不再編譯這部分頭檔案,僅僅使用預編譯的結果。這樣可以加快編譯速度,節省時間。
afx曾經是微軟一個專門的技術開發團隊,而stdafx.h則是這個團隊為了定義一些環境配置、參數設定等專門定義的。
工作原理
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就包含了那些通用的頭檔案。
預編譯頭檔案通過編譯stdafx.cpp生成,以工程名命名,由於預編譯的頭檔案的後綴是“pch”,所以編譯結果檔案是projectname.pch。
編譯器通過一個頭檔案stdafx.h來使用預編譯頭檔案。stdafx.h這個頭檔案名稱是可以在project的編譯設定里指定的。編譯器認為,所有在指令#include "stdafx.h"前的代碼都是預編譯的,它跳過#include "stdafx. h"指令,使用projectname.pch編譯這條指令之後的所有代碼。
因此,所有VC實現的CPP檔案第一條語句都是:#include "stdafx.h"。
檔案的問題
我們都知道,他是預編譯頭檔案,就是說,我們在stdafx.cpp里include一次,生成一次pch,pdb檔案,其他地方實際上直接用這個編譯的結果,從而減少編譯時間,提高編譯效率。一般,我們把常用的不變的庫頭檔案放裡面,如,atlbase.h,atlcore.h,windows.h等,通常的com里import進來的dll,tlb也放這個裡面,這樣,它能做到,只編譯一次,其他地方直接用編譯出的結果。
以上是如果stdafx被正確使用時,它確實大大提高我們編程的效率(你工作中,有多少時間是在等編譯完成?很多吧,這個時候一般都很無聊,無奈,浪費時間),但是他太容易用錯了。
如果在其他的.h檔案里也include "stdafx.h".則會產生問題
產生的問題描述:你的project里用了別人寫的.h檔案,導致你的編譯速度奇慢無比,而且你做任何小的修改,編譯都要好久好久,等的心煩,預編譯根本沒發揮作用。這個就可能給你h檔案的人用錯與編譯檔案了。
原因:由於你用到的.h檔案里include了stdafx,他在他本身的project里,vs能夠判斷的出他是預編譯頭,也能找的到需要的pch,pdb檔案。所以對寫這個.h檔案的人沒影響。但是你作為他的客戶,你工作在你的project下,你include了他的h頭檔案,而這時vs判斷不出他的頭檔案里include的stdafx是預編譯頭檔案,做普通檔案編。那可想而知,他的stdafx里如果有import外面大型的庫(如inventor的tlb,非常慢,我們犯了這個錯),那編譯速度簡直是煎熬。最要命的是,以後你做任何簡單的修改,這個stdafx都要重編,這和預編譯解決的問題恰好相反了。
所以, 絕對 不要在h頭檔案里(特別是發布給外面人用的h頭檔案)里include你的stdafx.h!