【问题标题】:Working with large header files处理大型头文件
【发布时间】:2018-07-25 07:12:20
【问题描述】:

首先介绍一下背景:

我正在使用 Visual Studio 2017 - 专业版

开发原生 C++ android 应用程序

我使用了标准模板。所以我有一个纯 c++ (11) 库,我的所有代码都在其中。以及链接到我的库的主项目中定义的预编译头文件。

我在做什么

我正在编写一些需要大量嵌入数据的代码。

我在谷歌上搜索了一些好的方法来做到这一点,但大多数方法似乎很麻烦,而且几乎总是有 cmets 说直接将数据放入头文件中,因为这是最便携的方法。

所以我现在有许多头文件,它们基本上包含静态数据数组。 注意它们不是 'const' 就好像你这样做了,如果你碰巧移动了变量定义,Visual Studio 2017 将尝试显示数据。所以只是静态的。

然后将所有头文件聚合到一个头文件中,然后最终在标准 cpp 文件中引用。有效地将数据设为该类的私有数据。

这一切都很好。但是编译时间变得非常慢。如果我观察输出窗口,我可以看到它花费了 80% 的时间在 cpp 文件上(即使数据或代码没有更改)

现在这不是编译器所能做的最好的。我希望编译器跳过这个,因为没有直接影响 cpp 文件的更改。

我还尝试将内容移到预编译的标头中。但这只会使 pch.h 文件每次构建都需要很长时间。

那我做错了什么?

更新

我已经仔细检查了文件没有被更改。 如果我按 F6 (build) 然后再按一次,它仍然会重建大文件。

我也尝试过修改静态数据,以便在 cpp 文件中定义它。 这仍然没有任何区别。

为清楚起见,这是一个示例:

.cpp 文件:

#include "Some.h"

unsigned char _someData[] =
{
   0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00,
};

unsigned char* Some::GetSomeData(void)
{
   return _someData;
}

.h 文件:

#pragma once

class Some
{
public:
static unsigned char* GetSomeData(void);
};

【问题讨论】:

  • 如果代码没有变化,编译器显然不应该重新编译。那是你应该看的地方。例如,比较源文件和目标文件的时间戳。其次,为什么将数据放在一个包含在一个 cpp 文件中的头文件中。为什么不直接将数据放在 cpp 文件中呢?这是最佳做法。
  • 稍后我会再次检查时间戳。数据位于 .h 文件中,因为数据是由另一个离线进程生成的。此过程可以重新创建 .h 文件而不会破坏其他任何内容。如果我希望数据直接在我的 cpp 文件中,那么我的工具集将需要更复杂并且“了解”更多关于系统的信息。那不是一个好的设计。
  • 忘了说我更喜欢非 android 唯一的解决方案。即我可以在本机 c++ 中做的事情,这样它就可以移植到苹果上工作。
  • 在一个cpp文件和一个getter函数中定义数据,并在.h文件中声明这个getter。顺便说一句,您使用什么框架来制作适用于 android 和 IOS 的应用程序?
  • 我可以确认在构建之间没有任何文件发生变化。只需连续按两次F6(构建)每次都会产生相同的效果(对cpp文件进行长时间编译)

标签: c++ compilation header header-files compiler-optimization


【解决方案1】:

以节省编译时间的方式尝试以下方法:

  1. 确保您的项目不包含丢失的文件。即使完全没有更改也会导致重新编译)。
  2. 不要将数据放在头文件中,将数据放在 c\cpp 文件中,并在头文件中使用数据变量的extern
  3. 不要包含来自其他标头的不必要的标头。 (标头的任何更改都会重新编译所有内容)
  4. 尽可能在标头中使用前向声明(而不是包含)。
  5. 注意#include <file>#include "file" 之间的区别。如果您选择了错误的包含方法(例如使用 包含您的文件,或使用 "" 包含系统包含),您将花费更多时间来搜索文件。
  6. 将包含目录从最常见到不太常见的顺序排列,也可以节省搜索文件的时间。

如果您想知道为什么即使没有更改项目或文件仍会重新构建或重新编译,您可以这样做:

  1. 菜单:工具 -> 选项
  2. 在打开的选项左盘中:项目和解决方案-> 构建和运行:
  3. 然后在右窗格中:将 MSBuild 项目构建输出详细程度更改为诊断。
  4. 构建项目
  5. 在诊断数据中查找重新编译的原因。

祝你好运

【讨论】:

  • 你的第一个数字 3 是重要的。当然,反复重新编译的原因是下一件事情,但修复它并不能解决编译时间过长的问题。
  • 好的,谢谢你的提示!我终于明白了。通过使用诊断设置,一切都清楚了。由于缺少文件,正在重建代码。因此,即使没有更改,它仍然会重建所有内容。一旦我有了这个细节,就很容易找到并解决问题。看起来我有一些奇怪的头文件没有被正确删除,但并不是真正需要的,所以没有阻止构建。非常感谢您的时间和帮助。
【解决方案2】:

您可以考虑使用在程序启动时读取的数据文件(在您的代码之外)。这会产生一些开销(文件读取时间),但您会解决编译时间问题。

【讨论】:

  • 我不相信在开发 android 应用程序时这是实际的/可能的。所有数据都必须包含在 APK 文件中。我将无法装载任何已发货的东西。除非你不知道?
  • 怎么办:1) 不发送数据文件 2) 首次应用启动时,下载数据文件,并将它们存储在存储中
  • 有趣的可能性。但这听起来像是 B 计划的解决方案。我期望编译器工作的方式必须有所改善。但谢谢你的好主意! +1
  • Jaudo,我得仔细看看,但对于本机 c++ / 跨平台,这似乎不适用于我的情况。 (忘了说这是跨平台的,但这就是我说便携的意思)
猜你喜欢
  • 1970-01-01
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-10
相关资源
最近更新 更多