Traditionally, the standard and portable way to avoid multiple header inclusions in C++ was/is to use the #ifndef - #define - #endif
pre-compiler directives scheme also called macro-guard scheme (see code snippet below).
传统上,避免c++中包含多个头的标准和可移植性的方法是/使用#ifndef - #define - #endifpre-compiler directive scheme也称为macroguard scheme(参见下面的代码片段)。
#ifndef MY_HEADER_HPP
#define MY_HEADER_HPP
...
#endif
In most implementations/compilers (see picture below) however, there's a more "elegant" alternative that serves the same purpose as the macro-guard scheme called #pragma once
. #pragma once
has several advantages compared to the macro-guard scheme, including less code, avoidance of name *es, and sometimes improved compile speed.
然而,在大多数实现/编译器(见下图)中,有一种更“优雅”的替代方案,它的作用与名为#pragma的宏观保护方案相同。与宏观保护方案相比,pragma曾经有几个优点,包括代码更少,避免名称冲突,有时还提高了编译速度。
Doing some research, I realized that although #pragma once
directive is supported by almost all known compilers, there's a turbidness on whether #pragma once
directive is part of the C++11 standard or not.
做了一些研究之后,我意识到尽管#pragma曾经的指令被几乎所有已知的编译器所支持,但是对于#pragma曾经的指令是否属于c++ 11标准的一部分,还是存在着一个模糊的问题。
Questions:
- Could someone clarify whether
#pragma once
directive is part of the C++11 standard or not? - 有人能澄清#pragma曾经的指令是否是c++ 11标准的一部分吗?
- If it's not part of the C++11 standard, are there any plans on including it on later releases (e.g., C++14 or later)?
- 如果它不是c++ 11标准的一部分,是否有计划在以后的版本中包含它(例如,c++ 14或更高版本)?
- It would also be nice if someone could further elaborate on the advantages/disadvantages in using either one of the techniques (i.e., macro-guard versus
#pragma once
). - 如果有人能进一步阐述使用其中任何一种技术(例如:,宏卫士和#pragma一次)。
2 个解决方案
#1
86
#pragma once
is not standard. It is a widespread (but not universal) extension, which can be used
#pragma一次不是标准。它是一个广泛的(但不是通用的)扩展,可以使用
- if your portability concerns are limited, and
- 如果您的可移植性问题是有限的,并且
- you can be sure that all of your include files are always on a local disk.
- 您可以确保包含的所有文件始终位于本地磁盘上。
It was considered for standardization, but rejected because it cannot be implemented reliably. (The problems occur when you have files accessible through several different remote mounts.)
它被认为是标准化的,但由于无法可靠地实现而被拒绝。(当您通过几个不同的远程挂载访问文件时,就会出现问题。)
It's fairly easy to ensure that there are no include guard conflicts within a single development. For libraries, which may be used by many different developments, the obvious solution is to generate a lot of random characters for the include guard when you create it. (A good editor can be set up to do this for you whenever you open a new header.) But even without this, I've yet to encounter any problems with conflicts between libraries.
很容易确保在单个开发中不存在包含保护冲突。对于可能被许多不同的开发所使用的库,显而易见的解决方案是在创建时生成大量的随机字符。(只要打开一个新的页眉,就可以为您设置一个好的编辑器。)但是,即使没有这些,我还没有遇到库之间冲突的任何问题。
#2
26
Section §16.6 of the Standard (N3936 draft) describes #pragma
directives as:
部分§16.6的标准(N3936草案)描述# pragma指令为:
A preprocessing directive of the form
表单的预处理指令。
# pragma pp-tokensopt new-line
causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner. Any pragma that is not recognized by the implementation is ignored.
使实现以实现定义的方式运行。这种行为可能导致翻译失败,或者导致翻译人员或结果程序以不符合的方式运行。未被实现识别的任何pragma都将被忽略。
Basically #pragma once
is an implementation specific instance of a #pragma
directive, and no, it's not standard. Yet.
基本上,#pragma一次是#pragma指令的一个特定实现实例,不,它不是标准的。然而。
It is often widely supported by most "major compilers" including GCC and Clang and is therefore sometimes recommended to avoid include-guards boilerplate.
它通常得到大多数“主要编译器”(包括GCC和Clang)的广泛支持,因此有时建议避免包含保护样板。
#1
86
#pragma once
is not standard. It is a widespread (but not universal) extension, which can be used
#pragma一次不是标准。它是一个广泛的(但不是通用的)扩展,可以使用
- if your portability concerns are limited, and
- 如果您的可移植性问题是有限的,并且
- you can be sure that all of your include files are always on a local disk.
- 您可以确保包含的所有文件始终位于本地磁盘上。
It was considered for standardization, but rejected because it cannot be implemented reliably. (The problems occur when you have files accessible through several different remote mounts.)
它被认为是标准化的,但由于无法可靠地实现而被拒绝。(当您通过几个不同的远程挂载访问文件时,就会出现问题。)
It's fairly easy to ensure that there are no include guard conflicts within a single development. For libraries, which may be used by many different developments, the obvious solution is to generate a lot of random characters for the include guard when you create it. (A good editor can be set up to do this for you whenever you open a new header.) But even without this, I've yet to encounter any problems with conflicts between libraries.
很容易确保在单个开发中不存在包含保护冲突。对于可能被许多不同的开发所使用的库,显而易见的解决方案是在创建时生成大量的随机字符。(只要打开一个新的页眉,就可以为您设置一个好的编辑器。)但是,即使没有这些,我还没有遇到库之间冲突的任何问题。
#2
26
Section §16.6 of the Standard (N3936 draft) describes #pragma
directives as:
部分§16.6的标准(N3936草案)描述# pragma指令为:
A preprocessing directive of the form
表单的预处理指令。
# pragma pp-tokensopt new-line
causes the implementation to behave in an implementation-defined manner. The behavior might cause translation to fail or cause the translator or the resulting program to behave in a non-conforming manner. Any pragma that is not recognized by the implementation is ignored.
使实现以实现定义的方式运行。这种行为可能导致翻译失败,或者导致翻译人员或结果程序以不符合的方式运行。未被实现识别的任何pragma都将被忽略。
Basically #pragma once
is an implementation specific instance of a #pragma
directive, and no, it's not standard. Yet.
基本上,#pragma一次是#pragma指令的一个特定实现实例,不,它不是标准的。然而。
It is often widely supported by most "major compilers" including GCC and Clang and is therefore sometimes recommended to avoid include-guards boilerplate.
它通常得到大多数“主要编译器”(包括GCC和Clang)的广泛支持,因此有时建议避免包含保护样板。