C++20新特性_模块(Modules)

文章目录

  • [第一章 C++20核心语法特性](#第一章 C++20核心语法特性)
    • [1.4 模块 (Modules)](#1.4 模块 (Modules))
      • [1.4.1 隔离原理](#1.4.1 隔离原理)
      • [1.4.2 示例](#1.4.2 示例)
      • [1.4.3 模块与头文件比较](#1.4.3 模块与头文件比较)

本文记录C++20新特性之模块 (Modules)。

第一章 C++20核心语法特性

1.4 模块 (Modules)

在C++20之前,C++和C包含头文件时,都使用#include包含,这是一种文本替换机制,主要可以概括三大痛点。

1 编译速度极慢:#include 仅仅是简单的文本复制。如果一个头文件被 100 个源文件包含,编译器就必须解析这个头文件 100 次。对于庞大的标准库(如 或 ),这带来了巨大的重复工作量。

2 宏隔离性差:头文件中定义的宏(Macros)会"泄漏"到包含它的源文件中,甚至影响后续包含的其他头文件,导致难以排查的命名冲突和 Bug。

3 依赖地狱:头文件的包含顺序可能会影响代码行为,且很难清晰地看到一个文件到底依赖了哪些具体符号.

C++20引入了模就是为了提供一种语义化、编译一次、隔离性强的代码共享机制,这是C++诞生40年来首次对代码头文件组织方式的一次变革。

1.4.1 隔离原理

模块引入了两个关键字 export 和 import

独立编译:模块单元(Module Unit)被编译成一种二进制格式(BMI, Binary Module Interface)。当其他文件 import 这个模块时,编译器直接读取这个预编译好的二进制接口,而不是重新解析源代码。这使得编译速度呈数量级提升。

真正的隔离:模块内部定义的宏、未导出的函数和类型,对外部是完全不可见的。import 一个模块不会像 #include 那样把一堆垃圾符号倒进你的全局命名空间。

初始化顺序:模块提供了更明确的初始化顺序保证,减少了"静态初始化顺序大灾难"发生的概率。

1.4.2 示例

下面示例中,定义一个模块math_utils.ixx,并在主模块中完成调用。

cpp 复制代码
export module math;	// 声明 这是一个 math 模块

// 2 导出 export 需要给外部使用的部分
export int add(int a, int b)
{
	return a + b;
}

// 没有 export 的函数,外部无法访问
int helper(int a) 
{
	return a * 2;
}

// 导出使用了非导出函数的函数
export int double_add(int a, int b) 
{
	return helper(add(a, b));
}

在主模块中导入 自定义模块:

cpp 复制代码
import math;        // 导入自定义的模块

    void test()
    {
        std::cout << "add() " << add(1, 2) << std::endl;
        // 3 
		std::cout << "double_add() " << double_add(5, 3) << std::endl;
        // 16 
    }

示例2:模块分区

对于大型项目,一个模块可能非常大,我们可以将模块分为多个分区,在一个主模块中汇总分模块。下面将math模块分为 sub和add分模块,然后在math主模块导出分模块内容。

math_add.ixx (分区文件)

cpp 复制代码
export module math:add; // 声明属于 math 模块的 add 分区

export int add(int a, int b) { return a + b; }

math_sub.ixx (分区文件)

cpp 复制代码
export module math:sub; // 声明属于 math 模块的 sub 分区

export int sub(int a, int b) { return a - b; }

math.ixx (主模块接口)

cpp 复制代码
export module math; // 定义主模块

export import :add; // 导出并重新发布 add 分区
export import :sub; // 导出并重新发布 sub 分区

1.4.3 模块与头文件比较

下面是模块和头文件的比较。

相关推荐
Mr_WangAndy2 小时前
C++20新特性_范围 `for` 循环的初始化语句
c++20·c++40周年·范围for初始化
Mr_WangAndy3 小时前
C++20新特性_三路比较运算符 (<=>)
c++20·c++40周年·三路比较运算符
Mr_WangAndy3 小时前
C++20新特性_consteval 和 constinit
c++20·c++40周年·consteval·constinit
Mr_WangAndy4 小时前
C++20新特性_协程(Coroutines)
c++20·c++20新特性·c++40周年·c++20协程
Mr_WangAndy4 小时前
C++20新特性_Lambda 改进
c++20·c++20新特性·c++40周年·lambda表达式改进
Mr_WangAndy13 小时前
C++17 新特性_第二章 C++17 语言特性_std::any和string_view
c++·string_view·c++40周年·c++17新特性·c++新特性any
Mr_WangAndy16 小时前
C++17 新特性_第一章 C++17 语言特性___has_include,u8字符字面量
c++·c++40周年·c++17新特性·__has_include·u8字面量
Mr_WangAndy1 天前
C++17 新特性_第二章 C++17标准库特性_std::invoke和std::invoke_result_t
c++·invoke·c++40周年·c++17新特性·invoke_result
Mr_WangAndy1 天前
C++14 新特性_第二章 C++14 标准库特性_std::exchange,std::quoted
c++·exchange·c++40周年·quoted·c++14新特性