预编译头未生效的主因是编译器未实际使用stdafx.h或pch.h:需确保.cpp文件设为“使用预编译头(/yu)”,仅一个文件(如stdafx.cpp)设为“创建(/yc)”,且其首行非注释#include必须为该头;仅包含稳定、高频、大体积头文件;跨平台时注意clang/gcc命名与cmake版本兼容性;sdk更新后须强制重建pch。

预编译头没生效,stdafx.h 或 pch.h 只是摆设
很多项目加了 stdafx.h 却没提速,根本原因是编译器根本没用它。Visual Studio 默认只对标记为“使用预编译头”的源文件才去读取 stdafx.h;如果某个 .cpp 文件属性里“预编译头”设成了“不使用”,那它就完全绕过整个机制。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 右键每个
.cpp文件 → “属性” → “C/C++” → “预编译头” → 确保设为“使用预编译头(/Yu)” - 必须有且仅有一个文件(通常是
stdafx.cpp)设为“创建预编译头(/Yc)” -
#include "stdafx.h"必须是该文件中**第一个非注释、非空行的#include**,否则编译器会忽略 - 别在
stdafx.h里写条件编译(比如#ifdef DEBUG),不同配置下生成的 PCH 不兼容
头文件塞太多,stdafx.h 成了性能黑洞
有人把所有用得上的头全塞进 stdafx.h:STL、Boost、Qt、自定义模块……结果改一行业务代码,整个 PCH 失效重编,反而比不用还慢。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 只放**稳定、高频、体积大**的头文件,比如
<vector></vector>、<string></string>、<windows.h></windows.h>,别加"my_utils.h"这类常变的 - 避免在
stdafx.h中#include其他自定义头,尤其带宏或模板定义的——它们会让 PCH 对修改极度敏感 - 用
/showIncludes编译参数看实际包含链,确认哪些头真被“预编译”了,哪些只是被普通包含
跨平台项目硬套 MSVC 的 pch 路径和命名
Clang 和 GCC 支持预编译头,但行为和 MSVC 不同:g++ -x c++-header pch.h -o pch.h.gch 生成的文件名必须严格匹配源名,且不认 stdafx.h 这种约定;CMake 若没显式启用,target_precompile_headers() 在旧版本里默认不生效。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- Clang/GCC 下,预编译头文件名要和使用它的源文件保持一致(如
common.h→common.h.pch),且需手动指定-include common.h - CMake 3.16+ 才稳定支持
target_precompile_headers(),低于此版本得靠add_compile_options(-Xclang -include-pch -Xclang ...)手动拼 - 别在 CMakeLists.txt 里写死
stdafx.h,用$<config></config>区分 Debug/Release 的 PCH 输出路径,否则多配置构建时会冲突
改动系统头或 SDK 版本后,PCH 没自动重建
升级 Windows SDK 或更新 VS 工具集后,stdafx.h 依赖的底层系统头可能已变,但 MSVC 不会主动检测并重建 PCH——继续用旧 PCH 就可能链接失败或运行时崩溃。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- VS 中启用“工具 → 选项 → 项目和解决方案 → 构建并运行 → 在生成前检查预编译头是否过期”(勾选)
- CI 构建脚本里加清理步骤:
del /q "$(IntDir)stdafx.pch"或rm -f build/CMakeFiles/*.pch - 别把 PCH 放进版本库——它含绝对路径和编译器内部结构,换机器必坏
预编译头不是开关一开就加速的魔法,它是把“重复解析”换成“重复加载”的权衡。一旦头文件稳定性、构建一致性或跨工具链适配没控住,它就会从加速器变成阻塞点。










