内部与外部包括警卫
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.h
在 foo.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 文件中的任何地方进行检查,并正确拼写保护符号的名称。因此不是首选。
我听说您应该更喜欢写 内部包含守卫 而不是 外部包含守卫。
我在互联网上搜索过,但没有找到答案。
这是 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.h
在 foo.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 文件中的任何地方进行检查,并正确拼写保护符号的名称。因此不是首选。