【问题标题】:Is #pragma once part of the C++11 standard?#pragma 曾经是 C++11 标准的一部分吗?
【发布时间】:2014-07-04 22:56:34
【问题描述】:

传统上,避免在 C++ 中包含多个标头的标准且可移植的方法是使用 #ifndef - #define - #endifpre-compiler 指令方案,也称为 macro-guard scheme(参见下面的代码 sn-p)。

#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif

然而,在大多数实现/编译器(见下图)中,有一个更“优雅”的替代方案,其用途与称为#pragma once 的宏保护方案相同。 #pragma once 与宏守卫方案相比有几个优点,包括更少的代码、避免名称冲突以及有时提高编译速度。

做了一些研究,我意识到尽管几乎所有已知的编译器都支持#pragma once 指令,但#pragma once 指令是否是 C++11 标准的一部分还不清楚。

问题:

  • 有人能澄清#pragma once 指令是否属于C++11 标准吗?
  • 如果它不是 C++11 标准的一部分,是否有计划将其包含在更高版本(例如 C++14 或更高版本)中?
  • 如果有人能进一步详细说明使用其中任何一种技术的优点/缺点(例如,macro-guard 与 #pragma once),那就太好了。

【问题讨论】:

  • 顺便说一句,标准禁止使用双下划线作为标头保护,该标准为实现保留所有以双下划线开头的符号(除了其他符号)。
  • 也禁止使用前导下划线后跟大写字母。二、浊度在哪里?我只看到了编译器支持,没有人声称它是标准的一部分?
  • 对于第三个要点,请查看相关问题:Is #pragma once a safe include guard? 它有一种情况,标题保护工作但#pragma once 通常不工作。
  • possible duplicate 因为它回答了这个问题而没有提及 C++11。
  • 嗯,官方文档中没有编码,但是你可以将其视为de facto标准。

标签: c++ c++11 macros header-files c++14


【解决方案1】:

#pragma once标准。它是一种普遍的(但不是 通用)扩展,可以使用

  • 如果您对便携性的担忧有限,并且
  • 您可以确保所有包含文件始终位于本地磁盘上。

它被考虑标准化,但被拒绝,因为它 无法可靠实施。 (当你出现问题时 可以通过几个不同的远程挂载访问文件。)

确保没有包含保护是相当容易的 单一发展中的冲突。对于图书馆,可能 被许多不同的开发使用,显​​而易见的解决方案是 为包含防护生成大量随机字符 当你创建它时。 (可以设置一个好的编辑器来执行此操作 每当你打开一个新的标题。)但即使没有这个, 我还没有遇到任何冲突的问题 图书馆。

【讨论】:

  • 不仅仅是远程安装。硬链接、软链接、subst 结构(在 Windows 上)。它会变得非常混乱。
  • 为什么编译器不能使用 SHA-1 或 MD5 校验和来识别文件?
  • 如果每个主要编译器都支持它,我真的看不出不将某些东西放入标准中的意义。实际上,标准中的某些内容远不及此。此外,当我们谈论包含文件时,抱怨边缘问题似乎很愚蠢,其中文件名冲突已经是一个大问题。如果这种对 100% 无问题特性的需求被普遍应用于 #included 头文件的概念,那就太好了。
  • 如果您的代码通过符号链接或奇怪的挂载包含来自不同位置的某些文件,那么它已经不可移植。因此,争论 pragma once 不能可移植地实现本质上不可移植(甚至不应该考虑)的东西是 C++ 颠倒世界的又一废话。
  • @JoseAntonioDuraOlmos 我同意符号链接是一种操作系统功能,它超出了 C++ 语言的范围。因此出现了一个问题,为什么 C++ 委员会应该考虑超出语言范围的东西?试图保证不属于他们责任的事情没有任何意义 IMO。 DOS 仅支持每个文件名 8+3 个字符,但没有人认为必须删除 #include,因为人们可能会盲目地滥用该指令。 #pragma once 不会以任何方式限制可移植性,前提是您不会利用符号链接来破坏编译。
【解决方案2】:

标准(N3936 草案)的第 §16.6 节将 #pragma 指令描述为:

形式的预处理指令

# pragma pp-tokensopt new-line

使实现以实现定义的方式运行 方式。该行为可能会导致翻译失败或导致 翻译器或生成的程序以不合格的方式运行 方式。任何未被实现识别的编译指示都是 忽略。

基本上#pragma once#pragma 指令的特定实现实例,不,它不是标准的。然而。

大多数“主要编译器”通常都广泛支持它,包括 GCCClang,因此有时建议避免使用 include-guards 样板。

【讨论】:

  • 请注意,#pragma#define header-guard 都可以。
  • “任何未被实现识别的编译指示都会被忽略”。这是否意味着消息:Warning: unrecognized pragma directive 不符合?
  • “因此是避免包含守卫样板的推荐方法” - 一个非常大胆的声明。这是一种非标准方式,使用它的好处很少,而且在我的经验中几乎没有相关性,所以我不得不取消我的 +1。
  • @Yakk:如果有人写#define header-guard,他/她也没有理由写#pragma once
  • @Nawaz 编译器可以保留每个已为#pragma onced 的文件(按路径)的缓存,如果再次为#included,则可以跳过#include(甚至不打开文件)。 gcc does the same 带有标头保护装置,但它非常非常脆弱。 #pragma 一个很容易做到,头部保护一个很难。
猜你喜欢
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
相关资源
最近更新 更多