如果包括"assert.h"的每个文件都需要很长的编译时间吗?

Does it take long compilation time if every files including "assert.h"?

本文关键字:编译 时间 文件 assert 包括 如果      更新时间:2023-10-16

根据Mats Petersson的结果,我做了一些测试。我通过定义宏来打开和关闭断言的工作是不必要的。我的结论是:

  1. 包括标准标头,如 <cassert><vector><memory> 等,编译时间很少。我们不需要关心。
  2. 在包含您自己的文件时要小心。包括那些真正需要的,因为依赖关系需要在更改依赖关系后重新编译。
  3. 包含类库的集合标头时要小心,例如 <QWidgets>(Qt 标头以包含其所有小部件)。这在编译中花费了大量时间。

[原文]

如果每个文件都包含"assert.h",编译时间是否很长?我认为在"math.h"或其他常见文件中也有类似的问题。我不喜欢预编译的标题。当我有一个 Vector3D 类时,就会发生这种情况,该类表示 3D 空间中具有 x、y、z 分量的向量。该类几乎无处不在。我有一个名为 component(int i) 的函数,其中断言 i 介于 0 和 2 之间。出于性能原因,我不将其实现放在 cpp 文件中。因此,"assert.h"几乎无处不在。

#pragma once
#include <assert.h>
/// A vector in a 3D space with 3 components: x, y, and z.
class Vector3D
{
public:
    Vector3D(float x = 0, float y = 0, float z = 0)
    {
        m_component[0] = x;
        m_component[1] = y;
        m_component[2] = z;
    }
    float x() const    {return m_component[0];}
    float y() const    {return m_component[1];}
    float z() const    {return m_component[2];}
    void setX(float x)    {m_component[0] = x;}
    void setY(float y)    {m_component[1] = y;}
    void setZ(float z)    {m_component[2] = z;}
    float component(int i) const
    {
        assert(i >= 0 && i < 3);
        return m_component[i];
    }
    float& component(int i)
    {
        assert(i >= 0 && i < 3);
        return m_component[i];
    }
private:
    float m_component[3];
};

受Floris Velleman的启发,我添加一个文件来定义我的ASSERT,以打开和关闭它。它需要使用断言在代码中将assert更改为ASSERT。谢谢。

#ifdef USE_ASSERT
# include <assert.h>
# define ASSERT(statement) assert(statement)
#else
# define ASSERT(statement)
#endif

所有标头都使用相同的包含模型,这非常慢。某些标头可能比其他标头更复杂,但通常,您不包含不需要的标头。

是的,在我的机器上,每个文件需要多花 0.03 秒(总共 0.1 秒,超过 30 个文件,包含 #include <assert.h>//#include <assert.h> 以及大约 90 行的大注释来填写文件。我将其复制了 30 次到单独的 .c 文件中,并使用 gcc -c *.c 进行编译。

但是,这几乎是"什么都没有"编译的。如果我们取而代之的是一些真实的C++代码,那么编译器必须"思考"一下,会发生什么:

基线(源代码 xx.cpp - 独立程序中大约 280 行C++代码,复制到名为 xx1 的文件 30 次.cpp .. xx30.cpp,使用 g++ -O2 -c *.cpp 编译):

7.722s      7.730s      7.660s

在列表末尾添加#include <cassert>

7.734s      7.652s      7.676s

我不认为这是一个重大变化。我敢肯定,如果您在每个头文件中都#include <assert.h>,并包含数百或数千个头文件,其中都包含 assert.h,也许它会有所作为。但我怀疑任何人都能够衡量一个真实项目的真正差异。

标准标头assert.h(您使用的是尖括号而不是引号,所以我假设您谈论的是标准 C assert 标头)是所有标准 C 库中最小的标头之一,因此在这种情况下,这真的无关紧要。断言的有用性比您可能获得的任何速度都重要。

注意:使用 in C++ cassert 代替 assert.h

另一方面,像iostream这样又大又复杂的标题...

 #ifndef AssertIncluded
 #define AssertIncluded
 #include "assert.h"
 #endif

不是 100% 确定语法,但这可能会摆脱双重包含的东西。至于速度,编译时间会根据必须发生的事情的数量而增加。包含更多文件意味着:"更长的编译时间"。