【问题标题】:Internal vs External Include Guards内部与外部包括警卫
【发布时间】:2015-08-27 15:33:13
【问题描述】:

我听说你应该更喜欢编写internal include guards而不是external include guards
我在互联网上搜索过,但没有找到答案。

这是 Herb 和 Andrei 的《C++ 编码标准》一书的 sn-p,其中显示了“外部包含保护”:

避免使用旧版本中提倡的过时的外部包含守卫 书籍:

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

现在,这就引出了下面的问题:

问: 什么是内部包含防护,什么是外部包含防护?两者有什么区别,为什么首选内部包含守卫?
我希望答案也提供一个例子。

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

【问题讨论】:

  • 请编辑您的问题并举例说明。
  • 从未听说过这个术语。你从哪里读到的?
  • @vsoftco C++ 编码标准,Herb Sutter 和 Andrei Alexandrescu 提到的一个
  • #pragma once 也不错。即使是非标准的,它也受到所有主要编译器的支持。怎么从来没有标准化过
  • @vsoftco 我最终回答了我自己的问题,我今天也确实学到了一些新东西。

标签: c++ header-files include-guards


【解决方案1】:

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

在这里,foo.h 定义了一个“内部包含保护”(大多数人简称为“包含保护”,因为这是传统的做法)。

// foo.h
#ifndef _FOO_H__
#define _FOO_H__

// ...

#endif  // _FOO_H__

相比之下,bar.hfoo.h 之外使用foo.h 的包含防护。我们可以将其称为“外部包含守卫”。

// bar.h
#ifndef _BAR_H__
#define _BAR_H__

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

// ...

#endif  // _BAR_H__

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

【讨论】:

  • 哪一个提高了编译速度?
  • 您在第二个示例中是否在#ifndef _FOO_H__ 下方缺少#define _FOO_H__?我相信使用外部标头保护时的假设是包含的头文件本身没有标头保护,因此#define 没有自己的保护。
  • 我也听说过这叫做“冗余包含保护”
  • 但为什么首选内部?
  • @AndreasDM 如果它是内部的,那么您不必记住将包含保护放在包含受保护文件的每个文件中。假设您有一个非常有用的头文件,您将其包含在项目的五个不同位置。你想写一次包含守卫,还是记得写五次,当你宁愿考虑其他问题时?
【解决方案2】:

经过一番深入研究,我现在可以回答我自己的问题了。

内部包含保护:

在被包含的头文件内容周围放置“include guards”的常用习语:

header.h

#ifndef HEADER_H
#define HEADER_H

// Contents of include file

#endif

因此,即使标头被#includeed 多次处理,标头的内容也将被处理一次
这被称为“内部包含保护”,因为保护完全在头文件内部。


外部包含防护:

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

header2.h

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

// Rest of header file goes here

行:#ifndef HEADER_H 仍然在header.h 中定义和检查内部。但是通过外部检查它,编译器可能完全避免打开文件。
只有当头文件包含在其他头文件中时,才建议检查外部
如果包含在源文件中,则不需要进行检查。


结论:

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

【讨论】:

  • 您也可以编辑安德烈的答案来改进它。
  • @ereOn 我同意你的观点,我没有考虑过。感谢您指出。
猜你喜欢
  • 2011-07-19
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 2011-06-19
  • 1970-01-01
  • 2016-04-13
相关资源
最近更新 更多