c++20 modules 是绕过预处理的全新编译单元机制,非头文件替代品;需用 export module 定义接口单元,import 导入模块,不支持 #include 语法,编译依赖模块名而非路径,构建链路重构导致当前项目落地困难。

C++20 Modules 不是“头文件替代品”,而是彻底绕过预处理的全新编译单元机制——它不解决“包含慢”,而是让“包含”这个动作本身消失。
怎么写一个最简 module interface unit
模块接口单元(.ixx 或 .cppm)必须以 export module 开头,且不能有 #include;导出符号用 export 显式声明:
export module math_utils;
export int add(int a, int b) { return a + b; }
export namespace math {
export const double PI = 3.14159;
}
注意:export module 后面的名称(如 math_utils)是模块名,不是文件名;编译器靠模块名识别依赖,而非路径。
怎么在另一个文件里 import 而不是 include
使用 import 语句导入模块,它不展开文本、不触发宏、不污染全局命名空间:
立即学习“C++免费学习笔记(深入)”;
import math_utils;
int main() {
auto x = add(2, 3); // OK
auto y = math::PI; // OK
// #include <iostream> // ❌ 不再需要
// std::cout << x; // ❌ std 未导入
}
常见错误:
-
import必须出现在翻译单元最前面(在任何声明、using、甚至空行之前) - 不能
import普通头文件(如import <iostream></iostream>是非法的,除非该头文件已封装为 module) - 标准库模块目前仍非完全可用:MSVC 支持
import std;(需 /std:c++20 /experimental:module),GCC 13+ 仅支持import <vector></vector>等有限封装,Clang 尚未落地标准库 module
编译时怎么生成和使用 module interface
不同编译器模块构建流程差异极大,没有统一“头文件式”的即用方式:
- MSVC:用
/interface编译.ixx生成 .ifc 文件,再用/reference引入;import语句会自动查找 .ifc - GCC:用
-fmodules-ts -x c++-system-header预编译标准头为 module,或用-fmodule-file=xxx.gcm指定接口文件 - Clang:需
-x c++-system-header+-fmodules+-fimplicit-modules,但 C++20 标准 module 支持仍在实验中
关键点:.ifc / .gcm 是二进制接口文件,不可编辑、不可跨编译器复用;模块缓存位置由编译器管理(如 MSVC 的 /module:cache),不是项目目录下的普通文件。
为什么你现在的项目还很难用上 Modules
Modules 不是开关一开就提速的优化项,它重构了整个构建链路:
- 构建系统要能识别
import依赖并调度编译顺序(CMake 3.28+ 才有target_compile_features(... PRIVATE cxx_modules)和add_module()) - 第三方库几乎都没有提供 module interface(Boost、fmt、spdlog 全是头文件形式)
- 调试信息、IDE 补全、静态分析工具对 module 支持滞后(VS 2022 对 module 的 IntelliSense 已较好,CLion 和 VS Code C/C++ 插件仍有限)
- 混合使用
#include和import时,头文件若被 module 和非-module 文件重复包含,可能触发 ODR 违规
真正落地的模块化路径,往往从封装内部工具库开始,而不是替换 <string></string> 或 <vector></vector> —— 那些地方的瓶颈从来不在预处理,而在模板实例化和符号解析。










