我目前正在做一个大项目,维护所有这些包括 guard 让我抓狂!手写是令人沮丧的浪费时间。尽管许多编辑器可以生成包含守卫,但这并没有多大帮助:
编辑器根据文件名生成保护符号。当您在不同目录中具有相同文件名的 header 时,会出现此问题。他们都将获得相同的包括后卫。将目录结构包含在保护符号中需要编辑器采取一些奇特的方法,因为宏中的斜杠和反斜杠并不是最好的选择。
当我必须重命名文件时,我也应该重命名所有包含保护(在 ifndef 中,定义最好是 endif 的注释)。烦人。
预处理器充斥着大量符号,却不知道它们的含义。
尽管定义被包含一次,编译器仍然会在每次遇到头包含时打开头。
包含守卫不适合命名空间或模板。事实上,他们正在颠覆命名空间!
你的守卫符号有可能不是唯一的。
当程序在单个目录中包含少于 1000 个 header 时,也许它们是可接受的解决方案。但如今呢?它很古老,与现代编码习惯无关。最困扰我的是,这个问题几乎可以通过#pragma once 指令完全解决。为什么不是标准?
最佳答案
像 #pragma once
这样的指令以具有明确明确好处的完全可移植方式定义并非易事。它提出问题的一些概念在所有支持 C
的系统上都没有得到很好的定义,并且以简单的方式定义它可能不会比传统的包含保护提供任何好处。
当编译遇到#pragma once
时,应该如何识别这个文件,使其不再包含它的内容?
显而易见的答案是文件在系统上的唯一位置。如果系统对所有文件都有唯一的位置,但许多系统提供链接(符号链接(symbolic link)和硬链接(hard link)),这意味着"file"没有唯一的位置,这很好。是否应该仅仅因为通过不同的名称找到该文件而重新包含该文件?应该不会吧。
但是现在有一个问题,如何定义 #pragma once
的行为以在所有平台上都具有确切含义 - 即使是那些甚至没有目录的平台,更不用说符号链接(symbolic link)了——并且仍然在拥有它们的系统上获得理想的行为?
您可以说文件身份由其内容决定,因此如果包含的文件具有 #pragma once
并且包含的文件完全相同内容,则第二个和后续的 #include
将无效。
这很容易定义并且具有明确定义的语义。它还具有良好的特性,例如,如果将项目从支持和使用文件系统链接的系统移动到不支持并使用文件系统链接的系统,它的行为仍然相同。
不利的一面是,每次遇到包含 #pragma once
的包含文件时,都必须使用 #pragma once
包括到目前为止。这意味着在任何情况下都类似于使用 #include
保护的性能损失,并给编译器编写者增加了不小的负担。显然,这个结果可以被缓存,但是对于传统的包含守卫也是如此。
传统的包含保护强制程序员选择一个宏作为包含文件的唯一标识符,但至少该行为定义明确且易于实现。
考虑到潜在的陷阱和成本,以及传统的包含保护确实有效的事实,标准委员会认为没有必要标准化 #pragma once
对我来说并不奇怪。
https://stackoverflow.com/questions/1695807/