#pragma once的可携式替代方案

10

有人能告诉我一些针对各种编译器支持#pragma once指令的解决方法吗?

我想在我的头文件中使用类似以下的语句:

#if _MSC_VER > ... || __GNUC__ > ... || ...

#pragma once

#endif

也许它已经存在于boost源代码或您的代码中了?


对我来说,#pragma once 的最大优势是它消除了文件开头和结尾的“噪音”。(此外,它使预处理器指令的自动折叠更有用)。速度优势只适用于没有针对包含保护进行优化的编译器。一旦你开始添加所有这些#if/#endif,你就会失去这个优势,如果你必须要最大的可移植性,你应该使用包含保护。 - Tod
3个回答

20

使用头文件保护

#ifndef MY_HEADER_H
#define MY_HEADER_H

// ...

#endif    // MY_HEADER_H

有时你会看到这些与使用 #pragma once 组合在一起:

#pragma once

#ifndef MY_HEADER_H
#define MY_HEADER_H

// ...

#endif    // MY_HEADER_H

#pragma once 是非常广泛支持的


1
正如文档所述,#pragma once 除了 include guards 之外还可以提高性能。 - FrozenHeart
1
@NikitaTrophimov:这取决于你的编译器;有些会检测到包含保护并对其进行优化。除非你从软盘上编译,否则不会看到任何显著的性能提升。 - BatchyX
1
同时使用两者会有害。#pragma once 是特定于编译器的,可能会导致在不支持它或具有不同含义的编译器上编译失败。此外,在 include guards 之外编写任何内容可能会阻止编译器能够检测和优化它们以防止再次打开相同的文件。你应该永远不要使用 #pragma once - R.. GitHub STOP HELPING ICE
2
我刚好对同样的问题感到好奇,并找到了一张总结不同编译器支持pragma once信息的表格:https://en.wikipedia.org/wiki/Pragma_once#Portability。现在使用它似乎是相当安全的。 - Ivan
1
现在,关于#pragma once不受支持的问题已经被限制在两个方面:(1)使用硬件供应商特定编译器的嵌入式系统(并且该供应商可能已经倒闭),以及(2)复古计算机,在这些计算机上必须使用超过十年的工具链编译代码。 - rwong

6

#pragma once 是一种非标准的替代 include guards 的方法:

#ifndef HEADER_H
#define HEADER_H

//contents of header

#endif

两者都确保头部内容不会在同一翻译单元内重复粘贴。


25
Clang、g++、Intel C++ 和 Visual C++ 都支持 #pragma once。我使用过的现代 C++ 编译器都支持该指令。 - James McNellis
如果我使用C++11,那么请使用 #pragma once。 - paulm
@paulm C++11和#pragma once的关系是从哪里来的?你能提供一些信息/链接吗? - Dmitry Volosnykh
1
@JamesMcNellis 这很有趣,但我仍然好奇为什么Stroustrup先生建议不要使用pragma once https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md - Chenna V
2
@blueskin:“这不是标准,也不是可移植的……会将你限制在一个供应商那里。”他担心的是可移植性问题。C++被广泛使用。例如,一些人正在为嵌入式系统使用硬件特定的编译器。正如维基百科指出的一个缺点,#pragma once并不完美。但除此之外,它非常方便和好用,所以我个人认为如果你的编译器都支持它,就没有必要避免使用它。 - Jenix
显示剩余2条评论

1
我喜欢使用传统的包含保护(正如被接受的答案所推荐的那样)。这并不需要太多工作,而且你可以获得100%的可移植性。如果你正在编写一个库、发布代码示例等,最好使用老式语法以避免其他人遇到麻烦。
话虽如此,其他人在这里也指出了,#pragma once指令被绝大多数现代编译器支持,因此在自己的项目中使用它是相对不太可能会遇到问题的。
维基百科列出了支持该指令的编译器列表:

https://en.wikipedia.org/wiki/Pragma_once#Portability


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接