stdafx

stdafx

stdafx,名稱的英文全稱為Standard Application Framework Extensions,stdafx是一款應用程序,應用十分簡單。

stdafx.h中沒有函數庫,只是定義了一些環境參數,使得編譯出來的程序能在32位的操作系統環境下運行。

定義


名稱的英文全稱為: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 // MFC core and standard components
#include // MFC extensions
#include // MFC OLE classes
#include // MFC OLE dialog classes
#include // 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進來的dlltlb也放這個裡面,這樣,它能做到,只編譯一次,其他地方直接用編譯出的結果。
以上是如果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!