在大型C++项目中,编译速度慢是个常见问题。你可能改了一行代码,结果等编译花了好几分钟。这时候,预编译头文件(Precompiled Header, PCH)就能派上用场。
什么是预编译头文件
简单来说,预编译头文件就是把那些不常变动、但频繁包含的头文件提前处理一遍,生成一个二进制中间产物。下次编译时,编译器直接读这个产物,跳过重复解析过程。
比如你的项目里每个源文件都包含了<vector>、<string>、<iostream>这些标准库头文件,每次编译都要重新展开它们,非常耗时。把这些打包成预编译头后,编译器加载一次就够了。
加快编译速度最直接
最明显的好处就是快。尤其在Visual Studio这类IDE中,开启PCH后,修改一个.cpp文件的编译时间可能从十几秒降到一两秒。对于每天要编译几十次的开发者来说,省下来的时间很可观。
就像你每天上班坐地铁,如果每次都得从家门口走到地铁站再进闸机,很费时间。但如果办张常旅客卡,刷一下就过,效率自然高。预编译头文件就相当于这张“快速通行卡”。
减少重复工作
没有PCH时,每个.cpp文件包含相同的头文件,编译器就得重复解析语法树、检查宏定义、展开模板等操作。这些工作对每个文件几乎一样,白白浪费CPU资源。
用了PCH之后,这部分“体力活”只做一次。后续编译直接复用结果,减轻编译器负担,也降低开发机的发热和耗电。
实际使用示例
在Visual Studio中,默认的StdAfx.h或targetver.h就是干这个的。GCC和Clang也支持,比如用命令:
g++ -x c++-header stdafx.h -o stdafx.h.gch
之后在源文件中包含stdafx.h时,编译器会自动识别并使用预编译版本。
常见做法是在项目根目录建一个common.h:
#include <vector>
#include <string>
#include <map>
#include <memory>
// 其他稳定不变的头
然后把它设置为预编译头,在每个cpp顶部第一行include它即可。
注意事项
不是所有头都适合放进PCH。经常改动的头文件一旦变了,整个预编译结果就要重来,反而影响效率。应该只放那些稳定、通用、体积大的头,比如标准库、第三方库(如Qt、Boost)的公共部分。
另外,PCH文件本身占用磁盘空间,不同编译选项下还需要重新生成。所以在CI/CD流程中合理管理也很重要。