【问题标题】:C++ header guards around object and usage?C ++标头保护对象和用法?
【发布时间】:2013-11-17 01:38:48
【问题描述】:

我习惯于在我的对象周围放置标题防护,例如:

#ifndef SOMETHING_H
#define SOMETHING_H

class Something {
...
}
#endif

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

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

对于每个包含。估计这样比较好。为什么?物体周围有警卫是多余的吗?

【问题讨论】:

  • Are redundant include guards necessary? 的可能副本 这个问题的答案与您相关。
  • 对我来说似乎两者完全相同,我认为在头文件中声明会更好,因为它将始终受到保护,而在头文件之外它可以很容易被程序员遗忘
  • @Serdalis:你是对的,这是一个副本(它本身就是 stackoverflow.com/questions/1021357/… 的副本。显然我需要提高我的搜索能力。谢谢。
  • @MatthewPigram:我还认为将它们放在实现中是一个不好的地方,但根据其他问题,它确实缩短了编译时间。

标签: c++ include-guards


【解决方案1】:

这样做的目的是节省编译时间。当编译器看到#include "something.h" 时,它必须出去获取文件。如果它这样做十次,最后九次基本上等于:

#if 0
...
#endif

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

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

【讨论】:

  • 这在 5 年前是一个很好的答案。如今,编译器会处理这个问题。
  • @KonradRudolph 你很可能是对的;我没有使用足够多的不同编译器来说明对此的优化有多常见。我怀疑许多使用这种技术的程序员在几年前就开始使用它,只是坚持使用它,而不去检查它是否仍然需要。还值得指出的是,有很多公司使用超过五年的编译器,要么是因为他们针对的是较旧的平台,要么是因为升级似乎不值得花钱。
【解决方案2】:

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

以下是重点:

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

【讨论】:

  • 那个链接太棒了!谢谢。
【解决方案3】:

最好在头文件和类定义文件上有这个,这样编译时,如果循环引用一个文件(a.cpp引用ah和b.cpp,b.cpp也引用ah,ah不会再读一遍)或其他类似情况。

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

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

【讨论】:

  • 任何常量只有一个#define,它在.h文件中。守卫在 include 语句周围的其他任何地方。
【解决方案4】:

其背后的想法是预处理器无需打开头文件并读取内容即可确定该头文件先前已包含在内,从而在编译期间节省了一些时间。然而,现在大多数编译器已经smart enough 发现同一文件的多个包含并忽略后续出现。

【讨论】:

  • 那么这样就没有什么明显的收获了吗?
  • 即使你多次包含它,如果它已经被包含,包含守卫仍然不会读取代码。
  • @AlexandreTryHardLeblanc:我认为他的优势在于它节省了在读取任何代码之前物理打开头文件的时间。
  • 这似乎只有在不使用智能编译器的情况下才会加起来,并且只有在包含许多重复标头的大型项目中才会加起来
  • 确实如此,虽然我很确定大多数时候节省的编译时间可以忽略不计,我认为?
猜你喜欢
  • 2020-04-30
  • 1970-01-01
  • 2011-06-13
  • 2015-10-08
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
相关资源
最近更新 更多