与传统的头文件相比,c++20 中的模块会减少编译时间吗?

Will modules in c++20 reduce compile time compared to traditional header-files?

假设我们有模块接口源文件foo.ixx,其中定义了模块foo。我们使用

import foo;

在许多不同的 cpp 文件中。与许多不同的 cpp 文件中包含传统头文件 foo.h 的情况相比,编译时间会减少吗?如果减少编译时间,为什么会这样?

"从实现文件访问头文件的机制是使用来自 C 预处理器的 include 指令。换句话说,你的头文件被隐式复制了很多次。

一个项目中所有头文件的副本很多,编译器不得不一遍又一遍地遍历和解析。最明显的问题之一是代码编译时间。

模块有效地替换了头文件和预处理器包含指令。模块提出的解决方案表明我们摆脱了 C 预处理器的文本包含,因此摆脱了它的所有缺点。”[每个模块只处理一次。参见 Table 2]

Reference

是的,模块的优点之一是可以减少编译时间。为了进行比较,这是今天的完成方式:

// foo.hpp
// some code
// a.cpp
#include "foo.hpp"
// b.cpp
#include "foo.hpp"

现在,当编译 2 个翻译单元 a.cppb.cpp 时,some code 被文本包含到这些源文件中,因此 some code 被编译了两次。虽然链接器会注意最终的可执行文件中实际上只有一个定义,但编译器仍然需要编译 some code 两次,这是浪费精力。

有了模块,我们会有类似的东西:

// foo.hpp
export module foo;
// some code
// a.cpp 
import foo;
// b.cpp 
import foo;

现在编译过程不一样了;有一个中间阶段,foo.hpp 被编译成 a.cppb.cpp 可以使用的格式,这意味着实现文件不需要编译 some code,他们可以直接使用 some code 中的定义。

这意味着 foo.hpp 只需要编译一次,这可能会大大减少编译时间,尤其是随着使用模块接口单元的实现文件数量的增加。

Header 包含机制依赖于文本预处理(本质上类似于解释脚本语言);这是 time-consuming 并且由于程序员的错误而难以追踪的错误。 另一方面,模块导入机制是一种更智能的分离接口和实现的机制,可以更好地保证一致性和正确性。它提供了在同一个翻译单元中定义接口和实现的方法,从而可以将两者匹配并通知 lib 开发人员传统包含系统中不会注意到的错误。因此,不仅构建时间,而且整个开发周期都显着缩短。