传统上,C++ 库由头文件 + 在二进制文件中编译的实现组成(.a
, .so
, .dylib
, .dll
, ...)。头文件#include
在源代码中,二进制部分链接到最终的可执行文件。
C++20 中的模块会改变这种布局吗?如果是这样,操作系统是否必须升级它们分发其核心库的方式,例如 Linux 中的标准库或 Windows 中的其他核心 dll?
传统上,C++ 库由头文件 + 在二进制文件中编译的实现组成(.a
, .so
, .dylib
, .dll
, ...)。头文件#include
在源代码中,二进制部分链接到最终的可执行文件。
C++20 中的模块会改变这种布局吗?如果是这样,操作系统是否必须升级它们分发其核心库的方式,例如 Linux 中的标准库或 Windows 中的其他核心 dll?
绝对地。与传统的标头/库相比,模块是向用户表示库代码的一种非常不同的类型。模块的主要优点是让编译器将其解析到抽象语法树 (AST)的级别。每个模块只发生一次 - 与每次包含特定头文件时相反。因此,加速的一种可能性是将非常频繁的头文件转换为模块并节省大量编译器时间,而不是多次重新编译为 AST,而只需一次。AST 也适用于模板……它是对 C++ 语言的通用且完整的描述。
但这也是目前主要的“缺点”:AST 绝对依赖于编译器。供应商、系统甚至编译器版本之间没有稳定性。所以分发 AST 没有任何意义,至少在当前的工具链环境中是这样。
因此,据我了解,模块不容易替代常见的头文件/库。它们是轻量级(最好的仅标头)和可能在典型程序中多次包含的高度模板化代码的理想替代品。许多库,主要是标准库,都是这样的。但也有许多不同设计的库(小型 API + 重型二进制后端)。对于那些,我想,我们将不得不像以前一样继续使用包含/库。但是,C++ 是向后兼容的,因此将模块与包含混合在一起完全没有问题。
此外,模块可以只包装包含文件(例如,使用 API)。这可能不是一个非常强大的模块用法,但可能会导致更统一的编程模式。在这种情况下,您仍然需要将“so”或“dylib”或任何库链接到生成的代码。
因此,我相信未来某个时候会同时发布一些 C++ 模块,以及传统的头文件+库。模块本身可以拆分为许多文件(只有“导出”的符号对用户可见)。模块可能会遵循与标头非常不同的设计准则。“每个模块一个类”很可能不会有任何优势,而是“每个模块有一大堆逻辑连接的代码”。