C++20 modules 主要解决头文件导致的语义耦合、重复解析、宏污染和构建不确定性问题,编译加速仅为依赖实现和项目结构的副作用;其核心价值在于接口契约可验证、依赖可审计、宏作用域可收敛。

C++20 的 modules 并不能“从根本上加速编译速度”——它解决的是头文件机制带来的**语义耦合、重复解析、宏污染和构建不确定性**问题;编译速度提升是副作用,且高度依赖实现和项目结构。
为什么 #include 导致编译慢且不可靠
每次 #include ,编译器都得:重新打开文件、预处理(展开所有宏)、重解析整个头文件语法树、检查模板定义是否变化。即使同一头文件被包含 100 次,就做 100 次完整解析。
- 宏定义会跨文件泄漏(
DEBUG在 A.h 定义,意外影响 B.cpp) - 头文件顺序敏感(
#include必须在某些头之前) - 无法表达“我只导出
std::vector,不导出内部辅助类”这种接口粒度 - 构建系统无法精确判断哪个模块变更后需重编译哪些 TU(translation unit)
module interface unit(.ixx 或 .cppm)怎么写才真正起效
关键不是语法,而是**切断隐式依赖链**。一个 export module math; 文件里,必须显式 export import std; 或 export template ,否则不会被导入者看到。
- 非
export的声明/定义(如namespace detail { ... })不会进入模块 ABI,也不会被导入者解析 -
import不是文本包含,不触发预处理,不传播宏,不读取注释或未导出的 static_assert - Clang 和 MSVC 对
import的支持仍有限;目前更可靠的是用import std;(MSVC)或自定义模块封装 STL
export module myvec; export importexport import export namespace my { template class vector { std::unique_ptr data_; size_t size_ = 0; public: vector(std::initializer_list il); // ... }; }
为什么你用了 module 编译还是没变快
常见原因不是模块本身无效,而是构建流程没对齐:
立即学习“C++免费学习笔记(深入)”;
- 构建系统(CMake 3.28+)没启用
set_property(GLOBAL PROPERTY USE_FOLDERS ON)或没正确设置target_compile_features(... PRIVATE cxx_modules) - 混合使用
#include和import:只要有一个#include "legacy.h",整个 TU 就退回传统模式(尤其 GCC 13 尚不支持混合) - 模块分区(
module myvec:detail;)没拆分好,导致修改内部实现仍触发大量重编译 - 编译器缓存未开启(Clang 的
-fmodules-cache-path,MSVC 的/dM和 PCH 共存问题)
当前落地最痛的点:工具链割裂
不是语言问题,是生态断层:
- CMake 对模块的依赖图生成仍不成熟,
make clean后首次构建可能漏掉 .pcm 编译 - IDE(如 VS Code + clangd)常无法跳转到
import的符号定义,因为没有统一的模块索引协议 - 静态库无法直接打包模块接口(.ifc/.pcm 是编译器私有格式),跨团队复用仍得回退到头文件
- CI 环境中不同编译器版本生成的 .pcm 不兼容,无法缓存共享
模块的价值不在“今天编译快 20%”,而在于让接口契约可验证、依赖可审计、宏作用域可收敛——这些好处要配合构建系统升级和团队规范才能释放。现在强行全量迁移,大概率换来一堆 module not found 和 CI 构建失败。









