如果我使用像 windows.h 这样的非模块头文件,我是否仍然应该在基于 C++ 20 模块的代码中使用预编译头文件?

问题描述 投票:0回答:1

我已经阅读了几篇关于 C++ 20 新功能“modules”的文章,并尝试在我的新项目中使用它们。但我不清楚的是我是否应该在编译器选项中禁用预编译头?

根据我的理解,我的源代码(模块实现文件)中包含的所有标头都进入全局模块范围并仅编译一次,因此不再使用预编译标头。

就我而言,我正在编写一个 Windows DLL,它高度依赖于 windows.h 头文件。这是相当大的头文件,它不是 C++ 20 模块接口文件,只是普通的头文件。

我的模块实现文件看起来像这样:

// ModuleA.cpp
module;

#include <windows.h>

module ModuleA;

void Initialize() {
   // Some code..
}

我的项目中有很多这样的*.cpp文件。

此外,我还在我的 *.ixx(模块接口)文件中包含 windows.h 标头,因为没有这个标头,他们对 DWORDSHORTUINTAPIENTRY 一无所知 类型。当然,我可以使用 unsigned long 代替 DWORD__stdcall 代替 APIENTRY 等,但这对我来说不太方便。

我担心,如果我在 Visual Studio 2022 C++ 编译器选项中禁用预编译头选项,windows.h 文件将被编译多次。

c++ visual-c++ c++20 precompiled-headers c++-modules
1个回答
0
投票

由于我在这里没有得到任何答案,所以我决定测试 C++ 20 模块与经典代码编译速度。 我创建了 20 个 C++ 项目中的 4 个:

  • 经典代码(无 C++ 20 模块)预编译头文件。
  • 经典代码(无 C++ 20 模块)with预编译头文件。
  • 基于现代 C++ 20 模块的代码预编译头文件。
  • 基于现代 C++ 20 模块的代码预编译头文件。

每个项目都包含 500 个头文件和 500 个经典代码项目的源文件。 以及 500 个模块接口文件 (.ixx) 和 500 个模块实现文件 (.cpp),用于基于 Modern C++ 20 模块的项目。 所有源文件和模块实现文件都有

#include "framework.h"
表示非预编译头文件版本,
#include "pch.h"
表示启用了预编译头文件的版本。

“framework.h” 文件包含以下标头:

// framework.h #pragma once #include <Windows.h> #include <TlHelp32.h> #include <iostream>
结果如下:

// █ Classic code, no Precompiled Header █ 1>All 510 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. 1>Finished generating code 1>NoModules-NoPCH.vcxproj -> \x64\Release\NoModules-NoPCH.exe ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== ========== Build completed at 22:05:55 and took 03:50.216 minutes ========== Build output folder size: 659 MB (691 732 507 bytes) // █ Classic code with Precompiled Header █ 1>All 510 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. 1>Finished generating code 1>NoModules-PCH.vcxproj -> \x64\Release\NoModules-PCH.exe ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== ========== Build completed at 22:06:39 and took 04.573 seconds ========== Build output folder size: 90.9 MB (95 344 891 bytes) // █ Modern C++ 20 code (Modules), no Precompiled Header █ 1>All 515 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. 1>Finished generating code 1>Modules-Cpp20.vcxproj -> \x64\Release\Modules-Cpp20.exe 1>Done building project "Modules-Cpp20.vcxproj". ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== ========== Build completed at 22:12:03 and took 04:30.789 minutes ========== Build output folder size: 1.47 GB (1 586 401 470 bytes) // █ Modern C++ 20 code (Modules) with Precompiled Header █ 1>All 510 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. 1>Finished generating code 1>Modules-Cpp20-PCH.vcxproj -> \x64\Release\Modules-Cpp20-PCH.exe 1>Done building project "Modules-Cpp20-PCH.vcxproj". ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ========== ========== Build completed at 22:13:10 and took 19.306 seconds ========== Build output folder size: 249 MB (261 284 309 bytes)
到目前为止,

最快编译是启用预编译头的经典C++代码,花费了04.573秒。创建的 *.obj 类文件:90.9 MB(95 344 891 字节)。

最慢带模块的现代C++ 20代码,但没有预编译头文件,花费了04:30.789分钟。还创建了很多 *.obj 之类的 1.47 GB(1 586 401 470 字节)的东西。

我将测试项目上传到 GitHub:

cpp20-compiler-tests。 我不认为这些测试不是最好的,现实世界的项目可能会表现出不同的性能。我不知道。

但我相信它回答了我的问题:

我是否应该将预编译头与 C++ 20 模块一起使用?

并且它表明答案是

YES。 它表明 C++ 20 全局模块片段无法取代预编译头文件,至少在今天是这样。也许有一天,谁知道呢...

© www.soinside.com 2019 - 2024. All rights reserved.