0

0

C++20 Modules与传统头文件相比有何优势? (编译速度提升)

尼克

尼克

发布时间:2026-01-11 14:45:09

|

813人浏览过

|

来源于php中文网

原创

编译速度显著提升的根本原因是模块消除了重复解析和宏污染,使每个接口只处理一次;模块二进制接口(如.pcm)被直接导入,跳过预处理、词法及语法分析,预处理开销归零,依赖图不爆炸,且支持跨TU优化。

c++20 modules与传统头文件相比有何优势? (编译速度提升)

编译速度为何能显著提升?

根本原因在于模块(module)消除了重复解析和宏污染,让每个接口只被处理一次。传统头文件每次被 #include 就要重新预处理、词法分析、语法分析——哪怕同一份 vector 被 50 个源文件包含,就做 50 次相同工作;而模块二进制接口(如 .pcm 文件)生成后,其他翻译单元直接导入,跳过所有前端阶段。

  • 预处理开销归零:没有 #define 展开、#ifdef 判定、行拼接等操作
  • 头文件依赖图不再线性爆炸:import std.core; 不会隐式拖入整个 iostreamstring 的全部实现细节
  • 编译器可跨 TU 做更激进的内联与常量传播,因接口契约更稳定(无宏干扰)

实际项目中哪些场景提速最明显?

不是所有代码都受益均等。以下几类改动后实测加速比通常 >2×:

  • 大型模板库重度使用者(如 Eigen、Boost.Hana):模板定义不再反复实例化解析
  • 含大量条件编译的跨平台代码(#ifdef _WIN32 / #ifdef __linux__):模块接口段不参与预处理,逻辑更干净
  • 单个头文件被数百个 .cpp 包含(如公共配置头 config.h):改用模块后,该接口只编译一次
  • 构建系统未启用 PCH 或 PCH 维护成本高的项目:模块天然替代 PCH,且无需手动管理“预编译什么”

为什么 import 不能完全替代 #include

当前主流编译器(MSVC / Clang / GCC)对模块的支持仍有限制,尤其涉及遗留代码时:

  • C 风格头文件(如 )无法直接 import,需通过模块接口单元(MIU)桥接,例如 MSVC 的 import 是特例支持,并非标准行为
  • 宏定义无法跨模块导出:#define LOG(x) printf("%s\n", x) 写在模块里,导入方看不到——这既是限制,也是优势(避免宏污染)
  • 某些 IDE 和构建系统(如旧版 CMake)尚未原生识别 .ixx.cppm,需手动配置规则,容易漏掉依赖声明
  • 模块接口单元(export module)中不能出现未定义行为代码(如未初始化变量),编译器会在接口编译阶段报错,而头文件中这类问题可能延迟到实例化才暴露

一个最小可验证提速对比示例

假设有一个常用工具utils.h,被 100 个 .cpp 文件包含;改写为模块后,仅需一次接口编译:

ClippingMagic
ClippingMagic

魔术般地去除图片背景

下载

立即学习C++免费学习笔记(深入)”;

// utils.ixx
export module utils;
export namespace util {
    inline int square(int x) { return x * x; }
}

对应传统头文件方式需重复解析百次,而模块方式:

  • 首次构建:编译 utils.ixx → 生成 utils.pcm(耗时 ≈ 单次头文件解析 ×1.5,含序列化开销)
  • 后续构建:100 个 .cpp 全部 import utils;,仅加载 .pcm 二进制,耗时 ≈ 单次头文件解析 ×0.1
  • 修改 utils.ixx 后,仅重编 .pcm + 重新导入它的 TU,而非所有包含者

真实大型项目中,模块化后 clean build 时间下降 30–60%,incremental build 可快 5–10 倍——但前提是模块粒度合理,且避免把所有东西塞进一个巨无霸模块里。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

107

2023.09.26

define的用法
define的用法

define用法:1、定义常量;2、定义函数宏:3、定义条件编译;4、定义多行宏。更多关于define的用法的内容,大家可以阅读本专题下的文章。

330

2023.10.11

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

72

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

279

2023.11.28

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1011

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

60

2025.10.17

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

80

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7万人学习

Git 教程
Git 教程

共21课时 | 2.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号