【问题标题】:Difference between pragma once inside and outside include guards?内部和外部的编译指示之间的区别包括警卫?
【发布时间】:2011-07-19 22:31:08
【问题描述】:

#pragma once 放置在包含保护内部和外部有什么区别?

案例一:

#ifndef SOME_HEADER_H
#define SOME_HEADER_H
#pragma once

案例2:

#pragma once
#ifndef SOME_HEADER_H
#define SOME_HEADER_H

出于好奇,我只是想知道是否有任何特殊情况我应该更喜欢其中一种(案例 1 或案例 2),因为我决定在我的代码中结合两者(pragma 和 header 保护)。

编辑:

我认为你们误解了我的问题...我问的是pragma once 的位置,而不是 pragma once -vs- header guards。

【问题讨论】:

  • 两者都包含是非常多余的,你不觉得吗?我只会使用定义进行检查。
  • @Tim:它们在识别“pragma once”的编译器上是非冗余的,但不执行 gcc 所做的巧妙优化,以发现何时标头保护允许它不打扰重新- 访问文件。至少某些版本的 MSVC 处于那种状态,不知道最新的。
  • 我认为你们误解了我的问题......我问的是 pragma once 的位置,而不是我是否应该使用 pragma once 或 header guards。

标签: c++ c include-guards


【解决方案1】:

如果在包含标头之前已经定义了SOME_HEADER_H,则存在细微差别,那么在第二种情况下,预处理器将处理#pragma once,而在第一种情况下则不会。

如果您#undef SOME_HEADER_H 并通过同一个 TU 再次包含该文件,您将看到功能上的差异:

#define SOME_HEADER_H
#include "some_header.h"
#undef SOME_HEADER_H
#include "some_header.h"

现在,在案例 1 中,我拥有头文件中的所有定义。在情况 2 中我没有。

即使没有#undef,由于#pragma once 在案例1 中被忽略,您可以想象到预处理时间的差异。这取决于实现。

我可以想到在第一次包含此头文件之前已经定义的两种可能的方式:

  • (很明显)一个完全独立的文件定义了它,无论是有意还是无意的名称冲突,
  • 该文件的副本已经定义了它。取决于可能包括此文件在两个不同文件名下涉及同一 TU 的情况的实现,例如因为符号链接或文件系统合并。如果您的实现支持#pragma once,并且您非常仔细地检查了它的文档,您可能能够找到一个明确的声明,是通过包含文件的路径应用优化,还是通过比较识别文件存储的内容,例如 inode 编号。如果是后者,您甚至可以弄清楚是否还有可以用来欺骗预处理器的骗局,例如远程挂载本地文件系统以隐藏它“确实是同一个文件”......

尽管以预期的方式使用,但只要实现以 Microsoft 定义的方式处理 #pragma once,则没有区别。只要它被处理而不是被跳过,它就会标记包含文件以进行优化,所以它是否会在第二遍文件中被处理并不重要——第二遍不会发生。

当然,由于 pragma 是非标准的,至少在理论上,它在不同的实现中可能具有完全不同的含义,在这种情况下,何时处理以及处理多少次可能很重要。在实践中,你会认为没有人会这样做。

【讨论】:

    【解决方案2】:

    它们是多余的。

    #pragma once 并非所有编译器都支持,而包含守卫则支持。只需使用包括警卫。像 gcc 这样的编译器足够聪明,可以理解包含守卫,甚至不会再次打开文件。

    【讨论】:

    • 尽管出于实际目的,所有著名的编译器都支持#pragma once
    【解决方案3】:

    回答你的问题:

    案例一:

    编译器将检查是否设置了预处理器常量,如果没有定义它,然后检查#pragma ońce 指令。这很可能是对字符串“SOME_HEADER_H”的哈希查找,以了解它是否已定义,然后再对当前文件名进行另一次哈希查找(可能是预处理器设置的 __ FILE __ 常量)。因此,如果该文件从未被读取,我们将进行两次哈希查找和两次哈希保存,如果文件已被读取,则只需一次哈希查找。

    案例 2:

    这显然与案例 1 相同,但顺序相反。所以我们唯一可以比较的是用作查找的哈希键的长度。根据当前头文件的路径,即路径的长度,#pragma once 指令的哈希查找的计算成本可能更高。如果文件名为“C:\dude.h”,则比“SOME_HEADER_H”短。

    所以我想总结一下。不,没有特殊情况,案例 1 比案例 2 更有益,反之亦然。至少不要对 Heureka 大喊大叫 ;)

    干杯

    【讨论】:

      猜你喜欢
      • 2015-08-27
      • 2013-11-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-05
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多