为何同时使用#pragma once与Include Guard?Boost库相关疑问
这问题问得太到位了!很多刚接触Boost的开发者都会有这个疑惑——明明Include Guard已经能解决头文件重复包含的问题,为啥还要多写一行#pragma once?其实Boost团队这么做是出于兼容性、编译效率和历史习惯的多重考量,咱们一一拆解:
全平台兼容性兜底
Include Guard是C标准明确支持的语法,不管是十年前的旧编译器,还是小众平台的特殊编译器,只要符合C标准就一定能识别。而#pragma once是编译器扩展,虽然现在主流的MSVC、GCC、Clang都支持,但还是存在一些边缘环境不兼容的情况。Boost作为要适配几乎所有C++编译环境的通用库,必须保证代码在任何环境下都能正常工作——Include Guard就是最可靠的兜底方案,#pragma once则是给支持它的编译器加的“额外buff”。编译效率的微小但可观的提升
你提到MSDN说同时用没有优势,这其实是针对MSVC编译器本身的结论。但在其他一些编译器的实现里,#pragma once可以让编译器直接通过文件系统的唯一性判断是否已经包含过该文件,不需要去解析和匹配宏定义(哪怕Boost的宏命名像BOOST_SERIALIZATION_ACCESS_HPP这种几乎不会冲突的)。对于Boost这种头文件数量极多、依赖关系复杂的库,每一次编译时少做一点宏匹配的工作,累积起来就能节省不少编译时间——而且加了#pragma once完全不会影响Include Guard的功能,相当于“不花成本的小优化”。历史遗留与行业惯例
Boost的代码库已经发展了二十多年,早期#pragma once还没被广泛支持的时候,大家都只用Include Guard。后来主流编译器陆续支持了#pragma once,Boost团队就顺手把它加上了,既不破坏原有代码的兼容性,又能跟上编译器的新特性。而且现在很多资深C开发者都习惯同时写Include Guard和#pragma once,算是一种行业通用的“双保险”写法,Boost作为C社区的标杆项目,自然也会延续这种惯例。
MSDN提到的“无优势”,其实是指在MSVC单独使用两种方案的效果相近,但Boost要考虑的是全平台的兼容性,而不是只针对某一款编译器。
内容的提问来源于stack exchange,提问作者shayan

