http://en.wikipedia.org/wiki/Pragma_once
当所有这些编译器都支持
#pragma once
时,我还应该使用包含防护吗?#pragma once
?
我不确定使用这两种方法是否只是在被广泛采用之前的建议,或者是否仍然有充分的理由使用这两种方法。
有没有仅使用
#pragma once
会导致问题的例子?
这取决于您的程序预期的可移植性。
只要您正在编写一个应该与您知道肯定支持
#prama once
的编译器一起工作的程序,只需使用#pragma once
就足够了。但这样做会将您的程序限制为支持实现定义功能的编译器集。
如果您需要您的程序在所有编译器上运行,那么您应该使用
#pragma once
并同时包含防护装置。
如果编译器不支持
#pragma once
,它会简单地忽略它[Ref#1],在这种情况下,标头保护将为您服务,因此,当您不知道时使用它们并没有什么问题您的目标编译器支持的功能。
因此,如果您希望您的程序在不同编译器上 100% 可移植,理想的方法仍然是仅使用包含防护。正如 @CharlesBailey 正确指出的那样,由于
#pragma once
的行为是实现定义的,未知编译器上的行为可能会对您的程序产生不利影响。
[参考#1]
标准 C++03:16.6 Pragma 指令
表单的预处理指令
# pragma pp-tokensopt new-line
使实现按照实现定义的方式运行。 任何未被实现识别的编译指示都会被忽略。
它是非标准的,所以如果您想安全,请使用包含防护装置
正如您的表格所示,现在很少遇到主流使用的编译器不支持
#pragma once
。为了保持代码库干净且维护成本低,需要不断地进行重构。每次重命名类或移动一些代码时都必须更新包含防护,这会给这项工作带来很大的负担。
所以我想说,除了一些特殊的极端情况或损坏的构建系统之外,
#pragma once
实际上是可以安全依赖的。如果您关心生产力和代码质量,则仅使用 #pragma once
似乎是显而易见的选择。
例外情况是,如果您正在编写一个需要支持世界上所有编译器的库,或者不幸的是必须使用不具有此功能的罕见编译器之一。