我还应该使用#include guards和#pragma一次吗?

Tre*_*key 34 c++ compiler-construction pragma include-guards

在此输入图像描述

http://en.wikipedia.org/wiki/Pragma_once
当所有这些编译器都支持时,我还应该使用包含保护#pragma once吗?
很多关于堆栈溢出的响应都表示要使用它们兼容,但我不确定它是否仍然是真的.今天哪些编译器不支持#pragma once

我不确定在它成为widley之前使用两者是否只是一个推荐,或者是否仍然有很好的理由使用这两种方法.
什么时候只使用#pragma once会导致问题的例子?

Alo*_*ave 14

这取决于您的程序预计可移植的程度.

只要你正在编写一个应该与你知道肯定支持的编译器一起工作的程序#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

导致实现以实现定义的方式运行.将忽略实现无法识别的任何编译指示.

  • 如果您希望程序的可移植性为100.00%,则需要使用包含保护,但您还需要避免使用`#pragma once`,因为未知编译器上的实现定义行为可能会对您的程序产生不利影响. (7认同)
  • 如果同一文件在操作系统/文件系统级别由两个不同的名称别名,则`#pragma once`将失败.但是,无论文件系统引用如何,文件中的#include-guard都将具有相同的名称,并且仍然可以使用. (3认同)

gvd*_*gvd 10

这是非标准的,所以如果你想安全使用包含警卫


Pet*_*rSW 7

如您的表所示,现在很少遇到主流使用中不支持的编译器#pragma once.为了保持代码库的清洁和廉价维护,需要不断进行重构.每次重命名类或移动一些代码时,必须更新包括警卫会给这项工作带来沉重的负担.

所以我会说,除了一些利基角落案件或破坏的构建系统#pragma once在实践中是安全的依赖.如果你关心生产力和代码质量只使用#pragma once似乎是明显的选择.

例外情况是,如果您正在编写一个需要在阳光下支持每个编译器的库,或者不幸的是必须使用这些没有此功能的稀有编译器之一.