用包含防护包围#include 是多余的吗?

问题描述 投票:0回答:4

我习惯在我的物体周围放置头部防护装置,例如:

#ifndef SOMETHING_H
#define SOMETHING_H

class Something {
...
}
#endif

但是我已经得到了他们也这样做的代码:

#ifndef SOMETHING_H
#include "something.h"
#endif

对于每个包含。据说,这样更好。为什么?物体周围有防护装置,这是多余的吗?

c++ include include-guards
4个回答
5
投票

这里对此进行了非常详细的讨论:
http://c2.com/cgi/wiki?RedundantIncludeGuards

以下是重点:

  • 是的,这是多余的,但对于某些编译器来说,它可能会更快,因为如果不需要,编译器将避免打开头文件。
  • “好的编译器使这个习惯用法变得不必要。他们注意到头文件使用了包含保护习惯用法(即文件中的所有非注释代码都用 #ifndef 括起来)。他们存储头文件的内部表并保护宏。在打开任何文件之前,它们会检查保护宏的当前值,然后跳过整个文件。”
  • “冗余守卫有几个缺点。它们使包含部分更难阅读。它们是多余的。它们泄露了守卫名称,这应该是标头的秘密实现细节。例如,如果有人重命名守卫他们可能会忘记更新所有假定守卫名称的地方。最后,如果有人在守卫之外添加代码,他们就会出错。当然,它们只是一个编译时效率黑客。仅当其他所有方法都失败时才使用。 ”

5
投票

其背后的想法是,预处理器不需要打开头文件并读取内容来确定该头文件之前是否已包含,从而在编译过程中节省了一些时间。然而,现在大多数编译器已经足够聪明能够发现同一文件的多个包含并忽略后续出现的情况。


0
投票

最好在头文件和类定义文件中使用这个,这样在编译时,如果在循环中引用一个文件(a.cpp引用了a.h和b.cpp,b.cpp也引用了a.h,a.h将不会被读取再次)或其他类似情况。

最让我担心的情况是你的问题是在不同的文件中定义相同的常量名称,并且可能会阻止编译器看到一些必要的常量、类、类型等。 “相信”该文件“已读”。

长话短说,将不同的 #ifndef 常量放在不同的文件中以防止混淆。


0
投票

这样做的目的是为了节省编译时间。当编译看到

#include "something.h"
时,它必须出去并获取文件。如果这样做十次,最后九次基本上等于:

#if 0
...
#endif

那么您就需要付出九次查找文件并从磁盘获取文件的成本,而没有任何实际好处。 (从技术上讲,编译器可以使用技巧来尝试减少或消除这种成本,但这就是其背后的想法。)

对于小程序来说,节省的费用可能不是很大,而且这样做也没有多大好处。对于包含数千个文件的大型程序,编译花费数小时的情况并不罕见,而这个技巧可以节省大量时间。就我个人而言,在编译时间开始成为真正的问题之前我不会这样做,并且像任何优化一样,我会在进行大量更改之前仔细查看实际成本在哪里。

© www.soinside.com 2019 - 2024. All rights reserved.