何时使用C++的包含保护或#pragma once?

6
在每个头文件中使用您选择的include guards和#pragma once是好的实践吗?或者仅在某些具有类声明等内容的头文件中使用?
我倾向于在每个头文件中都放置它,但我担心这样做无用且只会增加编译时间。那么,什么是良好的实践或常见做法呢?
让我澄清一下:我了解两者之间的区别。我想知道经验丰富的程序员是否在每个文件中都使用它,还是只在需要时使用它。

4
依我之见,你应该在每个头文件中添加 include guards。编译器重新编译已经包含的内容是没有意义的,而且出于维护的原因,即使你有一个头文件如果被包含两次不会产生错误,但以后可能会有人添加一些导致错误的内容。 - Galik
好的,这提出了一个我没有考虑到的问题:它增加的额外编译时间实际上会加速它,因为它不必重新复制头文件。 - Matthew D. Scholefield
请参考这个问题:https://dev59.com/gXM_5IYBdhLWcg3w-4dg?rq=1 - wingerse
据我所知,大多数编译器都足够智能,能够检测到包含保护文件的预处理指令,并省略对已读取的受保护文件的查找。而 #pragma once 的发明者要么不够聪明,要么想确保供应商锁定。运用奥卡姆剃刀原理来决定是哪一种情况... - Dietmar Kühl
3个回答

8

总结Galik的评论和我所意识到的:

在未来出现冲突的情况下,应该在每个头文件中加入包含保护。此外,编译器处理包含保护所需的时间很短,因此不需要处理额外的头文件,这将使编译速度更快。


6

#pragma once 是编译器特定的,而 普通 的 include guard 定义应该可以在任何 C++ 预处理器中使用。

因此,为了可移植性,始终坚持使用 "古老好用的" include guards 习惯。

使用 include guards 对于防止代码中出现 多个符号声明 错误至关重要。您不必担心 C++ 预处理器如何处理这个问题的假设或影响(现代预处理器非常优化,可以高效地处理这个问题)。


请查看澄清。 - Matthew D. Scholefield
5
这里的可移植性说法是虚假的,因为每个相关编译器都支持“#pragma once”。 - Griwes
@RandomPerson323 Galik在你的问题上的评论非常有帮助。在每个头文件中放置独特的包含保护,不要使用#pragma once!这是必须的。 - πάντα ῥεῖ
2
@RandomPerson323:“这是关于何时使用'when='的问题。” 那么,答案就是:每次 - πάντα ῥεῖ
1
@BlueMoon:你需要一堂阅读课:“在每个头文件中使用您选择的包含保护和#pragma once,还是只有那些具有类声明等内容的文件,这是一个好的实践吗?”<- 这在问题的原始版本中就有!请认真阅读。 - Griwes
显示剩余8条评论

2
如果你希望你的代码能够在所有C++编译器中都能够使用,你需要使用include guards。如果你认为你使用的编译器不太好并且需要使用#pragma once,你也可以添加这个指示:不理解它的编译器将忽略它。个人而言,我不会费心去使用#pragma once。这只是一个不存在的问题的解决方案:编译器完全可以检测include guards以避免重复打开已经包含的文件。

2
#pragma once 解决了一个真正的问题,这个问题是保持你定义的符号唯一。在遇到定义与文件位置不同步的文件时,使用UUID可能会让很多人失去耐心。在维基百科页面上列出的单个编译器不支持 #pragma once,但它现在并不能被认为是相关的:“当前(2014年)版本的XL C/C++编译器在AIX和Linux on Power上支持C++03标准的子集。” - Griwes
2
@Griwes:包含保护符解决了同样的问题。没有必要使用 #pragma once。而且,仅仅因为维基百科页面选择列出大多数支持 #pragma once 的编译器,并不意味着只有这一个编译器不支持它。例如,Oracle 的 CC 也不支持它(它恰好没有被列出)。 - Dietmar Kühl
1
我的观点是关于解决不同问题的,即解决“嗯,我应该在这个文件中使用哪个唯一名称作为包含防护的名称”。 - Griwes
1
就编译器而言,我确实预计会有许多不支持此功能的编译器,但我不认为其中任何一个与“现代”C++(即至少支持C++11;在完美的世界中,不支持C++11应该是编译器的死亡判决)有任何关联或支持。 - Griwes
@Griwes:是的,应该对包含保护名称应用一些合理的结构,但这不是一个真正的问题,完全可以管理。而且,是的,有些编译器供应商比较慢跟上标准,但这并不意味着它们是无关紧要的。在我工作的地方,我们同时使用CC和xlC,因为gcc无法处理我们的某些代码:CC和xlC更愿意处理这些要求(我并不是说这些要求实际上不是自己制造的问题,但它们是真实存在的)。 - Dietmar Kühl
显示剩余3条评论

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