内部与外部包括警卫

Internal vs External Include Guards

我听说您应该更喜欢写 内部包含守卫 而不是 外部包含守卫
我在互联网上搜索过,但没有找到答案。

这是 Herb 和 Andrei 的 C++ 编码标准一书的片段,显示了 "external include guard":

Avoid using the obsolete external include guards advocated in older books:

#ifndef FOO_HJNCLUDED_ //NOT recommended
#include "foo.h"
#define FOO_HJNCLUDED_
#endif

现在,这导致了下面的问题:

问: 什么是内部包含守卫,什么是外部包含守卫?两者有什么区别,为什么 internal include guards 更受欢迎?
我希望答案也能提供一个例子。

编辑:我最后回答了我自己的问题。

这是我看到的可能解释评论的内容。

在这里,foo.h 定义了一个 "internal include guard"(大多数人简称为 "include guard",因为这是传统的做法)。

// foo.h
#ifndef _FOO_H__
#define _FOO_H__

// ...

#endif  // _FOO_H__

相比之下,bar.hfoo.h 之外使用 foo.h 的包含守卫。我们可以将其昵称为 "external include guard".

// bar.h
#ifndef _BAR_H__
#define _BAR_H__

#ifndef _FOO_H__
#include "foo.h"
#endif

// ...

#endif  // _BAR_H__

我从事的一个(非常大的)项目声称这提高了编译速度,但这种说法是可疑的,因为在我看来这似乎是一个微不足道的编译器优化,而且我还没有看到任何指标来证明这种说法。但是,我们确实注意到包含多个头文件时阅读起来很烦人。

仔细研究之后,我现在可以回答我自己的问题了。

内部包含防护:

"include guards" 放在 header 个包含的文件的内容周围的常用习语:

header.h

#ifndef HEADER_H
#define HEADER_H

// Contents of include file

#endif

因此,header 的内容将被处理 一次,即使 header 被 #include 编辑了多次。
这被称为 "internal include guard" 因为守卫完全在 header 文件内部。


外部包含防护:

但是,上述方法可能存在问题如果编译器采用一种简单的方法,多次打开文件以检查"internal include guards" 这可能会导致大型项目的编译时间增加。

header2.h

#ifndef HEADER_H
#include "header.h"
#endif

// Rest of header file goes here

行:#ifndef HEADER_H 仍在 内部 定义并在 header.h 中检查。但是通过外部检查它,编译器可能根本不需要打开文件。
当 header 文件包含在其他 header 文件中时,仅 建议 检查 外部
从源文件中包含时不需要检查。


结论:

  • 内部守卫保证正确性
  • 外部保护可能会提高某些编译器的编译速度
    • 所涉及的成本是在一个 header 文件被#included 在另一个 header 文件中的任何地方进行检查,并正确拼写保护符号的名称。因此不是首选。